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
@@ -0,0 +1,20 @@
1
+ import {
2
+ createTracker,
3
+ createTrackerFromConfig,
4
+ getAllTrackers,
5
+ getPrimaryTracker,
6
+ getSecondaryTracker,
7
+ init_factory
8
+ } from "./chunk-3KYTNMSE.js";
9
+ import "./chunk-ZP6EWSZV.js";
10
+ import "./chunk-DMRTN432.js";
11
+ import "./chunk-ZHC57RCV.js";
12
+ init_factory();
13
+ export {
14
+ createTracker,
15
+ createTrackerFromConfig,
16
+ getAllTrackers,
17
+ getPrimaryTracker,
18
+ getSecondaryTracker
19
+ };
20
+ //# sourceMappingURL=factory-KKT7324R.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  init_projects,
3
3
  resolveProjectFromIssue
4
- } from "./chunk-ZMJFEHGF.js";
4
+ } from "./chunk-7ZB5D46Y.js";
5
5
  import "./chunk-ZTFNYOC7.js";
6
6
  import {
7
7
  __esm,
@@ -112,4 +112,4 @@ init_feedback_writer();
112
112
  export {
113
113
  writeFeedbackFile
114
114
  };
115
- //# sourceMappingURL=feedback-writer-T2WCT6EZ.js.map
115
+ //# sourceMappingURL=feedback-writer-IPPIUPDX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/cloister/feedback-writer.ts"],"sourcesContent":["/**\n * Feedback Writer — writes specialist feedback to workspace files.\n *\n * All specialist feedback (review, test, merge) is written to\n * .planning/feedback/ in the workspace, with a breadcrumb in STATE.md.\n * The work agent reads these on startup or after crash recovery.\n *\n * All I/O is async (fs/promises) — never execSync.\n */\n\nimport { writeFile, readFile, mkdir, readdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { resolveProjectFromIssue } from '../projects.js';\n\nexport interface WriteFeedbackOptions {\n issueId: string;\n workspacePath?: string;\n specialist: 'verification-gate' | 'review-agent' | 'test-agent' | 'inspect-agent' | 'uat-agent' | 'merge-agent';\n outcome: string;\n summary: string;\n markdownBody: string;\n}\n\nexport interface WriteFeedbackResult {\n success: boolean;\n /** Relative path from workspace root */\n relativePath?: string;\n /** Absolute path */\n filePath?: string;\n error?: string;\n}\n\n/**\n * Resolve workspace path from an issue ID.\n */\nfunction resolveWorkspacePath(issueId: string): string | null {\n const resolved = resolveProjectFromIssue(issueId);\n if (!resolved) return null;\n\n const wsPath = join(resolved.projectPath, 'workspaces', `feature-${issueId.toLowerCase()}`);\n return existsSync(wsPath) ? wsPath : null;\n}\n\n/**\n * Get the next sequence number from existing files in the feedback directory.\n */\nasync function getNextSequenceNumber(feedbackDir: string): Promise<number> {\n try {\n const files = await readdir(feedbackDir);\n let max = 0;\n for (const file of files) {\n const match = file.match(/^(\\d{3})-/);\n if (match) {\n const n = parseInt(match[1], 10);\n if (n > max) max = n;\n }\n }\n return max + 1;\n } catch {\n return 1;\n }\n}\n\n/**\n * Append a feedback entry to STATE.md's \"Specialist Feedback\" section.\n * Creates the section if it doesn't exist. Creates STATE.md if it doesn't exist.\n */\nasync function appendToStateMd(\n planningDir: string,\n entry: { timestamp: string; specialist: string; outcome: string; relativePath: string; issueId: string }\n): Promise<void> {\n const statePath = join(planningDir, 'STATE.md');\n const line = `- **[${entry.timestamp}] ${entry.specialist} → ${entry.outcome.toUpperCase()}** — \\`${entry.relativePath}\\``;\n\n let content: string;\n try {\n content = await readFile(statePath, 'utf-8');\n } catch {\n // STATE.md doesn't exist — create a minimal one\n content = `# Agent State: ${entry.issueId}\\n`;\n }\n\n const sectionHeader = '## Specialist Feedback';\n const sectionIndex = content.indexOf(sectionHeader);\n\n if (sectionIndex >= 0) {\n // Find the end of the section (next ## or EOF)\n const afterHeader = sectionIndex + sectionHeader.length;\n const nextSection = content.indexOf('\\n## ', afterHeader);\n const insertPos = nextSection >= 0 ? nextSection : content.length;\n content = content.slice(0, insertPos).trimEnd() + '\\n' + line + '\\n' + content.slice(insertPos);\n } else {\n // Append the section at the end\n content = content.trimEnd() + '\\n\\n' + sectionHeader + '\\n\\n' + line + '\\n';\n }\n\n await writeFile(statePath, content, 'utf-8');\n}\n\n/**\n * Write specialist feedback to a file in the workspace and update STATE.md.\n */\nexport async function writeFeedbackFile(opts: WriteFeedbackOptions): Promise<WriteFeedbackResult> {\n // Validate workspacePath — reject project roots (must contain /workspaces/ or have .planning dir)\n let providedPath = opts.workspacePath;\n if (providedPath && !existsSync(join(providedPath, '.planning')) && !providedPath.includes('/workspaces/')) {\n // Looks like a project root, not a workspace — fall back to resolution\n providedPath = undefined;\n }\n const workspacePath = providedPath || resolveWorkspacePath(opts.issueId);\n if (!workspacePath) {\n return { success: false, error: `Workspace not found for ${opts.issueId}` };\n }\n\n const planningDir = join(workspacePath, '.planning');\n const feedbackDir = join(planningDir, 'feedback');\n\n try {\n await mkdir(feedbackDir, { recursive: true });\n\n const seq = await getNextSequenceNumber(feedbackDir);\n const seqStr = String(seq).padStart(3, '0');\n const filename = `${seqStr}-${opts.specialist}-${opts.outcome}.md`;\n const filePath = join(feedbackDir, filename);\n const relativePath = `.planning/feedback/${filename}`;\n\n const timestamp = new Date().toISOString().replace(/\\.\\d+Z$/, 'Z');\n const shortTimestamp = timestamp.replace(/:\\d{2}Z$/, 'Z');\n\n const content = [\n '---',\n `specialist: ${opts.specialist}`,\n `issueId: ${opts.issueId}`,\n `outcome: ${opts.outcome}`,\n `timestamp: ${timestamp}`,\n '---',\n '',\n opts.markdownBody,\n '',\n ].join('\\n');\n\n await writeFile(filePath, content, 'utf-8');\n\n // Update STATE.md with breadcrumb\n await appendToStateMd(planningDir, {\n timestamp: shortTimestamp,\n specialist: opts.specialist,\n outcome: opts.outcome,\n relativePath,\n issueId: opts.issueId,\n });\n\n console.log(`[feedback-writer] Wrote ${relativePath} for ${opts.issueId}`);\n return { success: true, relativePath, filePath };\n } catch (error: any) {\n console.error(`[feedback-writer] Failed to write feedback for ${opts.issueId}:`, error);\n return { success: false, error: error.message };\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -21,18 +21,8 @@ import {
21
21
  restoreBackup,
22
22
  syncHooks,
23
23
  syncStatusline
24
- } from "./chunk-SUM2WVPF.js";
24
+ } from "./chunk-GM22HPYS.js";
25
25
  import "./chunk-AQXETQHW.js";
26
- import {
27
- GitHubTracker,
28
- GitLabTracker,
29
- LinearTracker,
30
- createTracker,
31
- createTrackerFromConfig,
32
- getAllTrackers,
33
- getPrimaryTracker,
34
- getSecondaryTracker
35
- } from "./chunk-UKSGE6RH.js";
36
26
  import {
37
27
  PROVIDERS,
38
28
  clearCredentialFileAuth,
@@ -63,12 +53,6 @@ import {
63
53
  loadConfig,
64
54
  saveConfig
65
55
  } from "./chunk-QAJAJBFW.js";
66
- import "./chunk-ZP6EWSZV.js";
67
- import {
68
- IssueNotFoundError,
69
- NotImplementedError,
70
- TrackerAuthError
71
- } from "./chunk-DMRTN432.js";
72
56
  import {
73
57
  AGENTS_DIR,
74
58
  ARCHIVES_DIR,
@@ -116,6 +100,22 @@ import {
116
100
  init_paths,
117
101
  isDevMode
118
102
  } from "./chunk-ZTFNYOC7.js";
103
+ import {
104
+ GitHubTracker,
105
+ GitLabTracker,
106
+ LinearTracker,
107
+ createTracker,
108
+ createTrackerFromConfig,
109
+ getAllTrackers,
110
+ getPrimaryTracker,
111
+ getSecondaryTracker
112
+ } from "./chunk-3KYTNMSE.js";
113
+ import "./chunk-ZP6EWSZV.js";
114
+ import {
115
+ IssueNotFoundError,
116
+ NotImplementedError,
117
+ TrackerAuthError
118
+ } from "./chunk-DMRTN432.js";
119
119
  import {
120
120
  init_esm_shims
121
121
  } from "./chunk-ZHC57RCV.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveGitHubIssue
3
- } from "./chunk-YAAT66RT.js";
3
+ } from "./chunk-WP6ZLWU3.js";
4
4
  import {
5
5
  getTmuxSessionName,
6
6
  init_specialists,
@@ -8,13 +8,13 @@ import {
8
8
  recordWake,
9
9
  spawnEphemeralSpecialist,
10
10
  wakeSpecialist
11
- } from "./chunk-TFPJD2I2.js";
11
+ } from "./chunk-3WDSD2VK.js";
12
12
  import "./chunk-JQBV3Q2W.js";
13
13
  import {
14
14
  init_workspace_config,
15
15
  replacePlaceholders
16
16
  } from "./chunk-AAP4G6U7.js";
17
- import "./chunk-ZN5RHWGR.js";
17
+ import "./chunk-4R6ATXYI.js";
18
18
  import "./chunk-USYP2SBE.js";
19
19
  import {
20
20
  init_config,
@@ -24,17 +24,17 @@ import {
24
24
  init_projects,
25
25
  loadProjectsConfig,
26
26
  resolveProjectFromIssue
27
- } from "./chunk-ZMJFEHGF.js";
27
+ } from "./chunk-7ZB5D46Y.js";
28
28
  import {
29
29
  init_tmux,
30
30
  sendKeysAsync,
31
31
  sessionExists
32
32
  } from "./chunk-W2OTF6OS.js";
33
- import "./chunk-ZP6EWSZV.js";
34
33
  import {
35
34
  PANOPTICON_HOME,
36
35
  init_paths
37
36
  } from "./chunk-ZTFNYOC7.js";
37
+ import "./chunk-ZP6EWSZV.js";
38
38
  import {
39
39
  init_esm_shims
40
40
  } from "./chunk-ZHC57RCV.js";
@@ -589,7 +589,7 @@ async function postMergeLifecycle(issueId, projectPath) {
589
589
  console.warn(`[merge-agent] Beads compaction failed: ${err}`);
590
590
  }
591
591
  try {
592
- const { getAgentState, saveAgentState } = await import("./agents-QXVDAW2M.js");
592
+ const { getAgentState, saveAgentState } = await import("./agents-M2ZOZL3P.js");
593
593
  const { killSession, sessionExists: sessionExists2 } = await import("./tmux-X2I5SAIJ.js");
594
594
  const agentId = `agent-${issueId.toLowerCase()}`;
595
595
  const agentState = getAgentState(agentId);
@@ -610,7 +610,7 @@ async function postMergeLifecycle(issueId, projectPath) {
610
610
  }
611
611
  try {
612
612
  const { findWorkspacePath } = await import("./archive-planning-U3AZAKWI.js");
613
- const { stopWorkspaceDocker } = await import("./workspace-manager-G6TTBPC3.js");
613
+ const { stopWorkspaceDocker } = await import("./workspace-manager-OWHLR5BL.js");
614
614
  const issueLower = issueId.toLowerCase();
615
615
  const workspacePath = findWorkspacePath(projectPath, issueLower);
616
616
  if (workspacePath) {
@@ -1015,7 +1015,7 @@ async function spawnMergeAgentForBranches(projectPath, sourceBranch, targetBranc
1015
1015
  const message = `Branch ${sourceBranch} is not pushed to remote.`;
1016
1016
  console.error(`[merge-agent] ${message}`);
1017
1017
  logActivity("merge_blocked", message);
1018
- const { writeFeedbackFile } = await import("./feedback-writer-T2WCT6EZ.js");
1018
+ const { writeFeedbackFile } = await import("./feedback-writer-IPPIUPDX.js");
1019
1019
  const blockMsg = `# Merge Blocked
1020
1020
 
1021
1021
  Branch "${sourceBranch}" is not pushed to remote.
@@ -1210,7 +1210,7 @@ Report any issues or conflicts you encountered.`;
1210
1210
  console.warn(`[merge-agent] Could not resolve project for ${issueId} \u2014 falling back to global specialist. Check projects.yaml configuration.`);
1211
1211
  }
1212
1212
  if (mergeProjectKey) {
1213
- const { getAgentRuntimeState, saveAgentRuntimeState } = await import("./agents-QXVDAW2M.js");
1213
+ const { getAgentRuntimeState, saveAgentRuntimeState } = await import("./agents-M2ZOZL3P.js");
1214
1214
  const IDLE_POLL_INTERVAL = 3e3;
1215
1215
  const IDLE_MAX_WAIT = 36e4;
1216
1216
  const idleStart = Date.now();
@@ -1722,4 +1722,4 @@ export {
1722
1722
  spawnMergeAgentForBranches,
1723
1723
  syncMainIntoWorkspace
1724
1724
  };
1725
- //# sourceMappingURL=merge-agent-O3TSBTLC.js.map
1725
+ //# sourceMappingURL=merge-agent-756U4NPX.js.map
@@ -19,7 +19,7 @@ import {
19
19
  resolveProjectPath,
20
20
  saveProjectsConfig,
21
21
  unregisterProject
22
- } from "./chunk-ZMJFEHGF.js";
22
+ } from "./chunk-7ZB5D46Y.js";
23
23
  import "./chunk-ZTFNYOC7.js";
24
24
  import "./chunk-ZHC57RCV.js";
25
25
  init_projects();
@@ -44,4 +44,4 @@ export {
44
44
  saveProjectsConfig,
45
45
  unregisterProject
46
46
  };
47
- //# sourceMappingURL=projects-3CRF57ZU.js.map
47
+ //# sourceMappingURL=projects-BPGM6IFB.js.map
@@ -11,7 +11,7 @@ import {
11
11
  extractTeamPrefix,
12
12
  findProjectByTeam,
13
13
  init_projects
14
- } from "./chunk-ZMJFEHGF.js";
14
+ } from "./chunk-7ZB5D46Y.js";
15
15
  import "./chunk-ZTFNYOC7.js";
16
16
  import {
17
17
  init_esm_shims
@@ -153,4 +153,4 @@ EOF`);
153
153
  export {
154
154
  createRemoteWorkspace
155
155
  };
156
- //# sourceMappingURL=remote-workspace-M4IULGFZ.js.map
156
+ //# sourceMappingURL=remote-workspace-LKRDGYEB.js.map
@@ -5,7 +5,7 @@ import {
5
5
  loadReviewStatuses,
6
6
  saveReviewStatuses,
7
7
  setReviewStatus
8
- } from "./chunk-IZIXJYXZ.js";
8
+ } from "./chunk-TA5X4QYQ.js";
9
9
  import "./chunk-JQBV3Q2W.js";
10
10
  import "./chunk-ZTFNYOC7.js";
11
11
  import "./chunk-ZHC57RCV.js";
@@ -17,4 +17,4 @@ export {
17
17
  saveReviewStatuses,
18
18
  setReviewStatus
19
19
  };
20
- //# sourceMappingURL=review-status-J2YJGL3E.js.map
20
+ //# sourceMappingURL=review-status-E77PZZWG.js.map
@@ -1,24 +1,24 @@
1
1
  import {
2
2
  getRecentRunLogs,
3
3
  init_specialist_logs
4
- } from "./chunk-TFPJD2I2.js";
4
+ } from "./chunk-3WDSD2VK.js";
5
5
  import "./chunk-JQBV3Q2W.js";
6
6
  import {
7
7
  getModelId,
8
8
  init_work_type_router
9
- } from "./chunk-ZN5RHWGR.js";
9
+ } from "./chunk-4R6ATXYI.js";
10
10
  import "./chunk-USYP2SBE.js";
11
11
  import "./chunk-QAJAJBFW.js";
12
12
  import {
13
13
  getProject,
14
14
  init_projects
15
- } from "./chunk-ZMJFEHGF.js";
15
+ } from "./chunk-7ZB5D46Y.js";
16
16
  import "./chunk-W2OTF6OS.js";
17
- import "./chunk-ZP6EWSZV.js";
18
17
  import {
19
18
  getPanopticonHome,
20
19
  init_paths
21
20
  } from "./chunk-ZTFNYOC7.js";
21
+ import "./chunk-ZP6EWSZV.js";
22
22
  import {
23
23
  __esm,
24
24
  init_esm_shims
@@ -257,4 +257,4 @@ export {
257
257
  regenerateContextDigest,
258
258
  scheduleDigestGeneration
259
259
  };
260
- //# sourceMappingURL=specialist-context-IKG6VMNH.js.map
260
+ //# sourceMappingURL=specialist-context-UBVUUFJV.js.map
@@ -16,15 +16,15 @@ import {
16
16
  isRunLogActive,
17
17
  listRunLogs,
18
18
  parseLogMetadata
19
- } from "./chunk-TFPJD2I2.js";
19
+ } from "./chunk-3WDSD2VK.js";
20
20
  import "./chunk-JQBV3Q2W.js";
21
- import "./chunk-ZN5RHWGR.js";
21
+ import "./chunk-4R6ATXYI.js";
22
22
  import "./chunk-USYP2SBE.js";
23
23
  import "./chunk-QAJAJBFW.js";
24
- import "./chunk-ZMJFEHGF.js";
24
+ import "./chunk-7ZB5D46Y.js";
25
25
  import "./chunk-W2OTF6OS.js";
26
- import "./chunk-ZP6EWSZV.js";
27
26
  import "./chunk-ZTFNYOC7.js";
27
+ import "./chunk-ZP6EWSZV.js";
28
28
  import "./chunk-ZHC57RCV.js";
29
29
  init_specialist_logs();
30
30
  export {
@@ -45,4 +45,4 @@ export {
45
45
  listRunLogs,
46
46
  parseLogMetadata
47
47
  };
48
- //# sourceMappingURL=specialist-logs-GFKUXCFG.js.map
48
+ //# sourceMappingURL=specialist-logs-FQRI3AIS.js.map
@@ -55,15 +55,15 @@ import {
55
55
  wakeSpecialist,
56
56
  wakeSpecialistOrQueue,
57
57
  wakeSpecialistWithTask
58
- } from "./chunk-TFPJD2I2.js";
58
+ } from "./chunk-3WDSD2VK.js";
59
59
  import "./chunk-JQBV3Q2W.js";
60
- import "./chunk-ZN5RHWGR.js";
60
+ import "./chunk-4R6ATXYI.js";
61
61
  import "./chunk-USYP2SBE.js";
62
62
  import "./chunk-QAJAJBFW.js";
63
- import "./chunk-ZMJFEHGF.js";
63
+ import "./chunk-7ZB5D46Y.js";
64
64
  import "./chunk-W2OTF6OS.js";
65
- import "./chunk-ZP6EWSZV.js";
66
65
  import "./chunk-ZTFNYOC7.js";
66
+ import "./chunk-ZP6EWSZV.js";
67
67
  import "./chunk-ZHC57RCV.js";
68
68
  init_specialists();
69
69
  export {
@@ -123,4 +123,4 @@ export {
123
123
  wakeSpecialistOrQueue,
124
124
  wakeSpecialistWithTask
125
125
  };
126
- //# sourceMappingURL=specialists-XMFCFGYQ.js.map
126
+ //# sourceMappingURL=specialists-CXRGSJY3.js.map
@@ -4,9 +4,9 @@ import {
4
4
  ensureProjectCerts,
5
5
  generatePanopticonTraefikConfig,
6
6
  generateTlsConfig
7
- } from "./chunk-43F4LDZ4.js";
7
+ } from "./chunk-VVTAPQOI.js";
8
8
  import "./chunk-QAJAJBFW.js";
9
- import "./chunk-ZMJFEHGF.js";
9
+ import "./chunk-7ZB5D46Y.js";
10
10
  import "./chunk-ZTFNYOC7.js";
11
11
  import "./chunk-ZHC57RCV.js";
12
12
  export {
@@ -16,4 +16,4 @@ export {
16
16
  generatePanopticonTraefikConfig,
17
17
  generateTlsConfig
18
18
  };
19
- //# sourceMappingURL=traefik-QXLZ4PO2.js.map
19
+ //# sourceMappingURL=traefik-X2IWTUHO.js.map
@@ -4,7 +4,7 @@ import {
4
4
  preTrustDirectory,
5
5
  removeWorkspace,
6
6
  stopWorkspaceDocker
7
- } from "./chunk-BYWVPPAZ.js";
7
+ } from "./chunk-KPGVCGST.js";
8
8
  import "./chunk-JT4O4YVM.js";
9
9
  import "./chunk-ZWZNEA26.js";
10
10
  import "./chunk-DW3PKGIS.js";
@@ -19,4 +19,4 @@ export {
19
19
  removeWorkspace,
20
20
  stopWorkspaceDocker
21
21
  };
22
- //# sourceMappingURL=workspace-manager-G6TTBPC3.js.map
22
+ //# sourceMappingURL=workspace-manager-OWHLR5BL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panopticon-cli",
3
- "version": "0.5.7",
3
+ "version": "0.5.9",
4
4
  "description": "Multi-agent orchestration for AI coding assistants (Claude Code, Codex, Cursor, Gemini CLI)",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -0,0 +1,73 @@
1
+ #!/bin/bash
2
+ # ~/.panopticon/bin/inspect-on-bead-close
3
+ # PostToolUse hook: auto-triggers pan inspect when agent closes a bead
4
+ #
5
+ # When a Bash command matches "bd close <beadId>", this hook:
6
+ # 1. Extracts the bead ID
7
+ # 2. Triggers pan inspect for the current issue
8
+ # 3. Outputs a message telling the agent to WAIT for inspection results
9
+ #
10
+ # This makes inspection mechanical — the agent doesn't need to remember
11
+ # to call pan inspect. The framework does it automatically.
12
+
13
+ # Don't use set -e - never break Claude Code execution
14
+ TOOL_INFO=$(cat 2>/dev/null || echo '{}')
15
+
16
+ # Only care about Bash tool
17
+ TOOL_NAME=$(echo "$TOOL_INFO" | jq -r '.tool_name // "unknown"' 2>/dev/null || echo "unknown")
18
+ if [ "$TOOL_NAME" != "Bash" ]; then
19
+ exit 0
20
+ fi
21
+
22
+ # Check if the command contains "bd close" (may be prefixed with "cd /path &&")
23
+ TOOL_INPUT=$(echo "$TOOL_INFO" | jq -r '.tool_input.command // ""' 2>/dev/null || echo "")
24
+ if ! echo "$TOOL_INPUT" | grep -qE "bd close "; then
25
+ exit 0
26
+ fi
27
+
28
+ # Extract bead ID(s) from the command — only the arguments after "bd close"
29
+ # Handles: "bd close myn-80 --reason=...", "cd /path && bd close MIN-796-14 --reason=..."
30
+ # Extract everything after "bd close " up to the first flag (--) or end of string
31
+ BD_CLOSE_ARGS=$(echo "$TOOL_INPUT" | sed 's/.*bd close //' | sed 's/ --.*//')
32
+ # Bead IDs are space-separated tokens (myn-80, MIN-796-14, panopticon-abc123)
33
+ BEAD_IDS=$(echo "$BD_CLOSE_ARGS" | tr ' ' '\n' | grep -E '^[a-zA-Z]' | head -5)
34
+ if [ -z "$BEAD_IDS" ]; then
35
+ exit 0
36
+ fi
37
+
38
+ # Get issue ID from env (set by pan work issue)
39
+ ISSUE_ID="${PANOPTICON_ISSUE_ID:-}"
40
+ if [ -z "$ISSUE_ID" ]; then
41
+ exit 0
42
+ fi
43
+
44
+ # Get first bead ID for inspection
45
+ FIRST_BEAD=$(echo "$BEAD_IDS" | head -1)
46
+
47
+ # Check if multiple beads were closed at once — this is a problem
48
+ BEAD_COUNT=$(echo "$BEAD_IDS" | wc -l)
49
+ if [ "$BEAD_COUNT" -gt 1 ]; then
50
+ echo ""
51
+ echo "⚠️ WARNING: You closed $BEAD_COUNT beads at once. The Inspect Specialist needs"
52
+ echo "one bead per commit to verify each change individually. Close beads ONE AT A TIME."
53
+ echo ""
54
+ fi
55
+
56
+ # Dispatch inspection (fire and forget — don't block the hook)
57
+ pan inspect "$ISSUE_ID" --bead "$FIRST_BEAD" > /dev/null 2>&1 &
58
+
59
+ # Output message that gets injected into the agent's conversation
60
+ echo ""
61
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
62
+ echo "🔍 INSPECTION DISPATCHED for bead $FIRST_BEAD"
63
+ echo ""
64
+ echo "The Inspect Specialist is now reviewing your changes against"
65
+ echo "the bead specification. It is working in YOUR workspace —"
66
+ echo "do NOT make changes or start the next bead until you receive:"
67
+ echo ""
68
+ echo " INSPECTION PASSED → proceed to next bead"
69
+ echo " INSPECTION BLOCKED → fix issues, commit fix, close bead again"
70
+ echo ""
71
+ echo "WAIT for the inspection result message."
72
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
73
+ echo ""
package/scripts/stop-hook CHANGED
@@ -64,5 +64,22 @@ if [ -x "$WORK_AGENT_HOOK" ]; then
64
64
  "$WORK_AGENT_HOOK" &
65
65
  fi
66
66
 
67
+ # Auto-mark planning complete when a planning agent finishes.
68
+ # The planning agent creates STATE.md + beads but the .planning-complete marker
69
+ # is only written by the dashboard "Done" button. If the user doesn't click it
70
+ # (or the system crashes), the marker is never created and Panopticon shows
71
+ # "Plan" instead of "Start Agent". This hook fixes that by calling
72
+ # complete-planning automatically when a planning-* agent stops.
73
+ if [[ "$AGENT_ID" == planning-* ]]; then
74
+ # Extract issue ID from agent ID (planning-min-796 → MIN-796)
75
+ ISSUE_ID=$(echo "$AGENT_ID" | sed 's/^planning-//' | tr '[:lower:]' '[:upper:]')
76
+ if [ -n "$ISSUE_ID" ]; then
77
+ # Fire and forget — don't block the stop hook
78
+ curl -s -X POST "http://localhost:3011/api/issues/$ISSUE_ID/complete-planning" \
79
+ -H "Content-Type: application/json" \
80
+ -d '{}' > /dev/null 2>&1 &
81
+ fi
82
+ fi
83
+
67
84
  # Always exit successfully
68
85
  exit 0