panopticon-cli 0.5.7 → 0.5.9

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 (61) hide show
  1. package/README.md +29 -83
  2. package/dist/{agents-QXVDAW2M.js → agents-M2ZOZL3P.js} +8 -6
  3. package/dist/{chunk-UKSGE6RH.js → chunk-3KYTNMSE.js} +1 -2
  4. package/dist/{chunk-UKSGE6RH.js.map → chunk-3KYTNMSE.js.map} +1 -1
  5. package/dist/{chunk-TFPJD2I2.js → chunk-3WDSD2VK.js} +52 -38
  6. package/dist/chunk-3WDSD2VK.js.map +1 -0
  7. package/dist/{chunk-ZN5RHWGR.js → chunk-4R6ATXYI.js} +5 -5
  8. package/dist/{chunk-ZMJFEHGF.js → chunk-7ZB5D46Y.js} +2 -2
  9. package/dist/{chunk-ZMJFEHGF.js.map → chunk-7ZB5D46Y.js.map} +1 -1
  10. package/dist/{chunk-SUM2WVPF.js → chunk-GM22HPYS.js} +10 -10
  11. package/dist/{chunk-BYWVPPAZ.js → chunk-KPGVCGST.js} +25 -2
  12. package/dist/{chunk-BYWVPPAZ.js.map → chunk-KPGVCGST.js.map} +1 -1
  13. package/dist/{chunk-4XR62WWV.js → chunk-QQ27EVBD.js} +10 -9
  14. package/dist/chunk-QQ27EVBD.js.map +1 -0
  15. package/dist/{chunk-IZIXJYXZ.js → chunk-TA5X4QYQ.js} +6 -2
  16. package/dist/{chunk-IZIXJYXZ.js.map → chunk-TA5X4QYQ.js.map} +1 -1
  17. package/dist/{chunk-43F4LDZ4.js → chunk-VVTAPQOI.js} +2 -2
  18. package/dist/{chunk-YAAT66RT.js → chunk-WP6ZLWU3.js} +28 -3
  19. package/dist/chunk-WP6ZLWU3.js.map +1 -0
  20. package/dist/cli/index.js +674 -268
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/dashboard/prompts/inspect-agent.md +157 -0
  23. package/dist/dashboard/prompts/uat-agent.md +215 -0
  24. package/dist/dashboard/prompts/work-agent.md +45 -5
  25. package/dist/dashboard/public/assets/{index-C7hJ5-o1.js → index-DqPey4Of.js} +62 -62
  26. package/dist/dashboard/public/index.html +2 -5
  27. package/dist/dashboard/server.js +2031 -1375
  28. package/dist/factory-KKT7324R.js +20 -0
  29. package/dist/{feedback-writer-T2WCT6EZ.js → feedback-writer-IPPIUPDX.js} +2 -2
  30. package/dist/feedback-writer-IPPIUPDX.js.map +1 -0
  31. package/dist/index.js +17 -17
  32. package/dist/{merge-agent-O3TSBTLC.js → merge-agent-756U4NPX.js} +10 -10
  33. package/dist/{projects-3CRF57ZU.js → projects-BPGM6IFB.js} +2 -2
  34. package/dist/{remote-workspace-M4IULGFZ.js → remote-workspace-LKRDGYEB.js} +2 -2
  35. package/dist/{review-status-J2YJGL3E.js → review-status-E77PZZWG.js} +2 -2
  36. package/dist/{specialist-context-IKG6VMNH.js → specialist-context-UBVUUFJV.js} +5 -5
  37. package/dist/{specialist-logs-GFKUXCFG.js → specialist-logs-FQRI3AIS.js} +5 -5
  38. package/dist/{specialists-XMFCFGYQ.js → specialists-CXRGSJY3.js} +5 -5
  39. package/dist/{traefik-QXLZ4PO2.js → traefik-X2IWTUHO.js} +3 -3
  40. package/dist/{workspace-manager-G6TTBPC3.js → workspace-manager-OWHLR5BL.js} +2 -2
  41. package/dist/workspace-manager-OWHLR5BL.js.map +1 -0
  42. package/package.json +1 -1
  43. package/scripts/inspect-on-bead-close +73 -0
  44. package/scripts/stop-hook +17 -0
  45. package/dist/chunk-4XR62WWV.js.map +0 -1
  46. package/dist/chunk-TFPJD2I2.js.map +0 -1
  47. package/dist/chunk-YAAT66RT.js.map +0 -1
  48. package/dist/feedback-writer-T2WCT6EZ.js.map +0 -1
  49. /package/dist/{agents-QXVDAW2M.js.map → agents-M2ZOZL3P.js.map} +0 -0
  50. /package/dist/{chunk-ZN5RHWGR.js.map → chunk-4R6ATXYI.js.map} +0 -0
  51. /package/dist/{chunk-SUM2WVPF.js.map → chunk-GM22HPYS.js.map} +0 -0
  52. /package/dist/{chunk-43F4LDZ4.js.map → chunk-VVTAPQOI.js.map} +0 -0
  53. /package/dist/{projects-3CRF57ZU.js.map → factory-KKT7324R.js.map} +0 -0
  54. /package/dist/{merge-agent-O3TSBTLC.js.map → merge-agent-756U4NPX.js.map} +0 -0
  55. /package/dist/{review-status-J2YJGL3E.js.map → projects-BPGM6IFB.js.map} +0 -0
  56. /package/dist/{remote-workspace-M4IULGFZ.js.map → remote-workspace-LKRDGYEB.js.map} +0 -0
  57. /package/dist/{specialist-logs-GFKUXCFG.js.map → review-status-E77PZZWG.js.map} +0 -0
  58. /package/dist/{specialist-context-IKG6VMNH.js.map → specialist-context-UBVUUFJV.js.map} +0 -0
  59. /package/dist/{specialists-XMFCFGYQ.js.map → specialist-logs-FQRI3AIS.js.map} +0 -0
  60. /package/dist/{traefik-QXLZ4PO2.js.map → specialists-CXRGSJY3.js.map} +0 -0
  61. /package/dist/{workspace-manager-G6TTBPC3.js.map → traefik-X2IWTUHO.js.map} +0 -0
@@ -9,7 +9,7 @@ import {
9
9
  init_work_type_router,
10
10
  popFromHook,
11
11
  pushToHook
12
- } from "./chunk-ZN5RHWGR.js";
12
+ } from "./chunk-4R6ATXYI.js";
13
13
  import {
14
14
  clearCredentialFileAuth,
15
15
  getProviderEnv,
@@ -27,7 +27,7 @@ import {
27
27
  getProject,
28
28
  init_projects,
29
29
  projects_exports
30
- } from "./chunk-ZMJFEHGF.js";
30
+ } from "./chunk-7ZB5D46Y.js";
31
31
  import {
32
32
  capturePaneAsync,
33
33
  confirmDelivery,
@@ -859,9 +859,9 @@ function recordWake(name, sessionId) {
859
859
  }
860
860
  async function spawnEphemeralSpecialist(projectKey, specialistType, task) {
861
861
  ensureProjectSpecialistDir(projectKey, specialistType);
862
- const { loadContextDigest } = await import("./specialist-context-IKG6VMNH.js");
862
+ const { loadContextDigest } = await import("./specialist-context-UBVUUFJV.js");
863
863
  const contextDigest = loadContextDigest(projectKey, specialistType);
864
- const { createRunLog: createRunLog2 } = await import("./specialist-logs-GFKUXCFG.js");
864
+ const { createRunLog: createRunLog2 } = await import("./specialist-logs-FQRI3AIS.js");
865
865
  const { runId, filePath: logFilePath } = createRunLog2(
866
866
  projectKey,
867
867
  specialistType,
@@ -881,7 +881,7 @@ ${basePrompt}`;
881
881
  const project = getProject(projectKey);
882
882
  const cwd = project?.path || getDevrootPath() || homedir2();
883
883
  try {
884
- const { preTrustDirectory } = await import("./workspace-manager-G6TTBPC3.js");
884
+ const { preTrustDirectory } = await import("./workspace-manager-OWHLR5BL.js");
885
885
  preTrustDirectory(cwd);
886
886
  } catch {
887
887
  }
@@ -889,7 +889,7 @@ ${basePrompt}`;
889
889
  try {
890
890
  const { stdout: sessions } = await execAsync('tmux list-sessions -F "#{session_name}" 2>/dev/null || echo ""', { encoding: "utf-8" });
891
891
  if (sessions.split("\n").map((s) => s.trim()).includes(tmuxSession)) {
892
- const { getAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
892
+ const { getAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
893
893
  const existingState = getAgentRuntimeState(tmuxSession);
894
894
  if (existingState?.state === "active") {
895
895
  return {
@@ -962,10 +962,10 @@ echo "## Specialist completed task"
962
962
  script -qfec "bash '${innerScript}'" /dev/null 2>&1 | tee -a "${logFilePath}"
963
963
  `, { mode: 493 });
964
964
  await execAsync(
965
- `tmux new-session -d -s "${tmuxSession}"${envFlags} "bash '${launcherScript}'"`,
965
+ `tmux new-session -d -s "${tmuxSession}" -c "${cwd}"${envFlags} "bash '${launcherScript}'"`,
966
966
  { encoding: "utf-8" }
967
967
  );
968
- const { saveAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
968
+ const { saveAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
969
969
  saveAgentRuntimeState(tmuxSession, {
970
970
  state: "active",
971
971
  lastActivity: (/* @__PURE__ */ new Date()).toISOString(),
@@ -989,7 +989,7 @@ script -qfec "bash '${innerScript}'" /dev/null 2>&1 | tee -a "${logFilePath}"
989
989
  }
990
990
  }
991
991
  async function buildTaskPrompt(projectKey, specialistType, task, contextDigest) {
992
- const { getSpecialistPromptOverride } = await import("./projects-3CRF57ZU.js");
992
+ const { getSpecialistPromptOverride } = await import("./projects-BPGM6IFB.js");
993
993
  const customPrompt = getSpecialistPromptOverride(projectKey, specialistType);
994
994
  let prompt = `# ${specialistType} Task - ${task.issueId}
995
995
 
@@ -1039,17 +1039,8 @@ Update status via API:
1039
1039
  - If issues found: POST to /api/workspaces/${task.issueId}/review-status with {"reviewStatus":"blocked","reviewNotes":"..."}
1040
1040
  - If review passes: POST with {"reviewStatus":"passed"} then queue test-agent`;
1041
1041
  break;
1042
- case "test-agent":
1043
- prompt += `Your task:
1044
- 1. Run the full test suite
1045
- 2. Analyze any failures in detail
1046
- 3. Identify root causes
1047
- 4. Update status via API when done
1048
-
1049
- Update status via API:
1050
- - If tests pass: POST to /api/workspaces/${task.issueId}/review-status with {"testStatus":"passed"}
1051
- - If tests fail: POST with {"testStatus":"failed","testNotes":"..."}`;
1052
- break;
1042
+ // test-agent: detailed prompt is in the second switch block below (line ~2173)
1043
+ // Do NOT add an inline stub here — it would shadow the detailed template.
1053
1044
  case "merge-agent": {
1054
1045
  const bInfo = await resolveWorkspaceGitInfo(task.workspace, task.branch);
1055
1046
  if (bInfo.isPolyrepo) {
@@ -1159,7 +1150,7 @@ async function terminateSpecialist(projectKey, specialistType) {
1159
1150
  console.error(`[specialist] Failed to kill tmux session ${tmuxSession}:`, error);
1160
1151
  }
1161
1152
  if (metadata.currentRun) {
1162
- const { finalizeRunLog: finalizeRunLog2 } = await import("./specialist-logs-GFKUXCFG.js");
1153
+ const { finalizeRunLog: finalizeRunLog2 } = await import("./specialist-logs-FQRI3AIS.js");
1163
1154
  try {
1164
1155
  finalizeRunLog2(projectKey, specialistType, metadata.currentRun, {
1165
1156
  status: metadata.lastRunStatus || "incomplete",
@@ -1172,20 +1163,20 @@ async function terminateSpecialist(projectKey, specialistType) {
1172
1163
  }
1173
1164
  const key = `${projectKey}-${specialistType}`;
1174
1165
  gracePeriodStates.delete(key);
1175
- const { saveAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
1166
+ const { saveAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
1176
1167
  saveAgentRuntimeState(tmuxSession, {
1177
1168
  state: "suspended",
1178
1169
  lastActivity: (/* @__PURE__ */ new Date()).toISOString()
1179
1170
  });
1180
- const { scheduleDigestGeneration } = await import("./specialist-context-IKG6VMNH.js");
1171
+ const { scheduleDigestGeneration } = await import("./specialist-context-UBVUUFJV.js");
1181
1172
  scheduleDigestGeneration(projectKey, specialistType);
1182
1173
  scheduleLogCleanup(projectKey, specialistType);
1183
1174
  }
1184
1175
  function scheduleLogCleanup(projectKey, specialistType) {
1185
1176
  Promise.resolve().then(async () => {
1186
1177
  try {
1187
- const { cleanupOldLogs: cleanupOldLogs2 } = await import("./specialist-logs-GFKUXCFG.js");
1188
- const { getSpecialistRetention } = await import("./projects-3CRF57ZU.js");
1178
+ const { cleanupOldLogs: cleanupOldLogs2 } = await import("./specialist-logs-FQRI3AIS.js");
1179
+ const { getSpecialistRetention } = await import("./projects-BPGM6IFB.js");
1189
1180
  const retention = getSpecialistRetention(projectKey);
1190
1181
  const deleted = cleanupOldLogs2(projectKey, specialistType, { maxDays: retention.max_days, maxRuns: retention.max_runs });
1191
1182
  if (deleted > 0) {
@@ -1373,7 +1364,7 @@ async function getSpecialistStatus(name, projectKey) {
1373
1364
  const sessionId = getSessionId(name, projectKey);
1374
1365
  const running = await isRunning(name, projectKey);
1375
1366
  const contextTokens = countContextTokens(name);
1376
- const { getAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
1367
+ const { getAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
1377
1368
  const tmuxSession = getTmuxSessionName(name, projectKey);
1378
1369
  const runtimeState = getAgentRuntimeState(tmuxSession);
1379
1370
  let state;
@@ -1467,7 +1458,7 @@ exec claude --dangerously-skip-permissions --session-id "${newSessionId}" --mode
1467
1458
  `, { mode: 493 });
1468
1459
  setSessionId(name, newSessionId);
1469
1460
  await execAsync(
1470
- `tmux new-session -d -s "${tmuxSession}"${envFlags} "bash '${launcherScript}'"`,
1461
+ `tmux new-session -d -s "${tmuxSession}" -c "${cwd}"${envFlags} "bash '${launcherScript}'"`,
1471
1462
  { encoding: "utf-8" }
1472
1463
  );
1473
1464
  recordWake(name);
@@ -1528,7 +1519,7 @@ async function wakeSpecialist(name, taskPrompt, options = {}) {
1528
1519
  const sessionId = getSessionId(name);
1529
1520
  const wasAlreadyRunning = await isRunning(name);
1530
1521
  if (wasAlreadyRunning && !options.skipBusyGuard) {
1531
- const { getAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
1522
+ const { getAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
1532
1523
  const runtimeState = getAgentRuntimeState(tmuxSession);
1533
1524
  if (runtimeState?.state === "active") {
1534
1525
  console.warn(`[specialist] ${name} is busy (working on ${runtimeState.currentIssue}), refusing to interrupt`);
@@ -1552,7 +1543,7 @@ async function wakeSpecialist(name, taskPrompt, options = {}) {
1552
1543
  }
1553
1544
  const cwd = getDevrootPath() || join4(process.env.HOME || "/home/eltmon", "Projects");
1554
1545
  try {
1555
- const { preTrustDirectory } = await import("./workspace-manager-G6TTBPC3.js");
1546
+ const { preTrustDirectory } = await import("./workspace-manager-OWHLR5BL.js");
1556
1547
  preTrustDirectory(cwd);
1557
1548
  } catch {
1558
1549
  }
@@ -1647,7 +1638,7 @@ async function wakeSpecialist(name, taskPrompt, options = {}) {
1647
1638
  }
1648
1639
  }
1649
1640
  recordWake(name, sessionId || void 0);
1650
- const { saveAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
1641
+ const { saveAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
1651
1642
  saveAgentRuntimeState(tmuxSession, {
1652
1643
  state: "active",
1653
1644
  lastActivity: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1749,14 +1740,14 @@ CRITICAL: Do NOT delete the feature branch.`;
1749
1740
  if (totalChangedFiles === 0) {
1750
1741
  staleBranch = true;
1751
1742
  console.log(`[specialist] review-agent: stale branch detected for ${task.issueId} \u2014 0 files changed vs main`);
1752
- const { setReviewStatus } = await import("./review-status-J2YJGL3E.js");
1743
+ const { setReviewStatus } = await import("./review-status-E77PZZWG.js");
1753
1744
  setReviewStatus(task.issueId.toUpperCase(), {
1754
1745
  reviewStatus: "passed",
1755
1746
  reviewNotes: "No changes to review \u2014 branch identical to main (already merged or stale)"
1756
1747
  });
1757
1748
  console.log(`[specialist] review-agent: auto-passed ${task.issueId} (stale branch)`);
1758
1749
  const tmuxSession = getTmuxSessionName("review-agent");
1759
- const { saveAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
1750
+ const { saveAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
1760
1751
  saveAgentRuntimeState(tmuxSession, {
1761
1752
  state: "idle",
1762
1753
  lastActivity: (/* @__PURE__ */ new Date()).toISOString()
@@ -1861,7 +1852,7 @@ curl -s -X POST ${apiUrl}/api/specialists/test-agent/queue -H "Content-Type: app
1861
1852
  const testWorkspace = task.workspace || "unknown";
1862
1853
  const testGitInfo = await resolveWorkspaceGitInfo(task.workspace, task.branch);
1863
1854
  const testIsPolyrepo = testGitInfo.isPolyrepo;
1864
- const { extractTeamPrefix, findProjectByTeam } = await import("./projects-3CRF57ZU.js");
1855
+ const { extractTeamPrefix, findProjectByTeam } = await import("./projects-BPGM6IFB.js");
1865
1856
  const testTeamPrefix = extractTeamPrefix(task.issueId);
1866
1857
  const testProjectConfig = testTeamPrefix ? findProjectByTeam(testTeamPrefix) : null;
1867
1858
  const testConfigs = testProjectConfig?.tests;
@@ -1989,6 +1980,29 @@ Then use send-feedback-to-agent skill to notify issue agent of NEW failures only
1989
1980
 
1990
1981
  **NEVER run test commands without redirecting to a file.** This is not optional.
1991
1982
 
1983
+ ## REQUIRED: Container Smoke Test
1984
+
1985
+ After unit tests pass, verify the Docker workspace frontend is accessible.
1986
+ This is NOT optional \u2014 UI changes that pass unit tests but break in containers must be caught.
1987
+
1988
+ \`\`\`bash
1989
+ # Check if containers are running for this workspace
1990
+ docker ps --filter "name=${featureName}" --format "{{.Names}} {{.Status}}" 2>/dev/null
1991
+ \`\`\`
1992
+
1993
+ If containers are running, test these URLs:
1994
+ - **Frontend**: \`curl -sk https://feature-${featureName}.${testProjectConfig?.workspace?.dns?.domain || "pan.localhost"}/ | head -5\`
1995
+ - **API proxy**: \`curl -sk https://feature-${featureName}.${testProjectConfig?.workspace?.dns?.domain || "pan.localhost"}/api/health\`
1996
+ - **API issues**: \`curl -sk https://feature-${featureName}.${testProjectConfig?.workspace?.dns?.domain || "pan.localhost"}/api/issues | head -100\`
1997
+
1998
+ **Pass criteria:**
1999
+ 1. Frontend returns HTML containing \`<div id="root">\`
2000
+ 2. \`/api/health\` returns JSON with \`"status":"ok"\`
2001
+ 3. \`/api/issues\` returns JSON array (not an error)
2002
+
2003
+ **If ANY of these fail, the test FAILS** \u2014 report via the API with details about which check failed.
2004
+ If containers are NOT running, note it but don't fail (containers may not be configured for this project).
2005
+
1992
2006
  IMPORTANT: Do NOT hand off to merge-agent. Human clicks Merge button when ready.`;
1993
2007
  break;
1994
2008
  }
@@ -2000,7 +2014,7 @@ IMPORTANT: Do NOT hand off to merge-agent. Human clicks Merge button when ready.
2000
2014
  async function wakeSpecialistOrQueue(name, task, options = {}) {
2001
2015
  const { priority = "normal", source = "handoff" } = options;
2002
2016
  const running = await isRunning(name);
2003
- const { getAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
2017
+ const { getAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
2004
2018
  const tmuxSession = getTmuxSessionName(name);
2005
2019
  const runtimeState = getAgentRuntimeState(tmuxSession);
2006
2020
  const idle = runtimeState?.state === "idle" || runtimeState?.state === "suspended";
@@ -2031,7 +2045,7 @@ async function wakeSpecialistOrQueue(name, task, options = {}) {
2031
2045
  };
2032
2046
  }
2033
2047
  }
2034
- const { saveAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
2048
+ const { saveAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
2035
2049
  saveAgentRuntimeState(tmuxSession, {
2036
2050
  state: "active",
2037
2051
  lastActivity: (/* @__PURE__ */ new Date()).toISOString(),
@@ -2131,7 +2145,7 @@ async function sendFeedbackToAgent(feedback) {
2131
2145
  }
2132
2146
  const agentSession = `agent-${toIssueId.toLowerCase()}`;
2133
2147
  const feedbackMessage = formatFeedbackForAgent(fullFeedback);
2134
- const { writeFeedbackFile } = await import("./feedback-writer-T2WCT6EZ.js");
2148
+ const { writeFeedbackFile } = await import("./feedback-writer-IPPIUPDX.js");
2135
2149
  const specialistMap = {
2136
2150
  "review-agent": "review-agent",
2137
2151
  "test-agent": "test-agent",
@@ -2151,7 +2165,7 @@ async function sendFeedbackToAgent(feedback) {
2151
2165
  return false;
2152
2166
  }
2153
2167
  try {
2154
- const { messageAgent } = await import("./agents-QXVDAW2M.js");
2168
+ const { messageAgent } = await import("./agents-M2ZOZL3P.js");
2155
2169
  const msg = `SPECIALIST FEEDBACK: ${fromSpecialist} reported ${feedback.feedbackType.toUpperCase()} for ${toIssueId}.
2156
2170
  Read and address: ${fileResult.relativePath}`;
2157
2171
  await messageAgent(agentSession, msg);
@@ -2660,4 +2674,4 @@ export {
2660
2674
  getFeedbackStats,
2661
2675
  init_specialists
2662
2676
  };
2663
- //# sourceMappingURL=chunk-TFPJD2I2.js.map
2677
+ //# sourceMappingURL=chunk-3WDSD2VK.js.map