panopticon-cli 0.5.6 → 0.5.7

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.
package/dist/cli/index.js CHANGED
@@ -16,7 +16,8 @@ import {
16
16
  init_database,
17
17
  init_review_status,
18
18
  loadReviewStatuses,
19
- saveReviewStatuses
19
+ saveReviewStatuses,
20
+ setReviewStatus
20
21
  } from "../chunk-IZIXJYXZ.js";
21
22
  import {
22
23
  checkBudget,
@@ -49,7 +50,7 @@ import {
49
50
  setSessionId,
50
51
  summarizeCosts,
51
52
  wakeSpecialistOrQueue
52
- } from "../chunk-WJJ3ZIQ6.js";
53
+ } from "../chunk-TFPJD2I2.js";
53
54
  import "../chunk-JQBV3Q2W.js";
54
55
  import {
55
56
  archivePlanning,
@@ -108,7 +109,7 @@ import {
108
109
  saveSessionId,
109
110
  spawnAgent,
110
111
  stopAgent
111
- } from "../chunk-FUUP55PE.js";
112
+ } from "../chunk-4XR62WWV.js";
112
113
  import {
113
114
  checkHook,
114
115
  clearHook,
@@ -244,9 +245,9 @@ import {
244
245
 
245
246
  // src/cli/index.ts
246
247
  init_esm_shims();
247
- import { readFileSync as readFileSync46, existsSync as existsSync52 } from "fs";
248
- import { join as join52 } from "path";
249
- import { homedir as homedir24 } from "os";
248
+ import { readFileSync as readFileSync45, existsSync as existsSync51 } from "fs";
249
+ import { join as join51 } from "path";
250
+ import { homedir as homedir23 } from "os";
250
251
  import { Command as Command2 } from "commander";
251
252
  import chalk62 from "chalk";
252
253
 
@@ -2200,15 +2201,13 @@ async function updateLinearStatus(apiKey, issueIdentifier) {
2200
2201
  try {
2201
2202
  const { LinearClient: LinearClient2 } = await import("@linear/sdk");
2202
2203
  const client = new LinearClient2({ apiKey });
2203
- const me = await client.viewer;
2204
- const teams = await me.teams();
2205
- const team = teams.nodes[0];
2206
- if (!team) return false;
2207
- const issues = await team.issues({ first: 100 });
2208
- const issue = issues.nodes.find(
2204
+ const searchResults = await client.searchIssues(issueIdentifier, { first: 1 });
2205
+ const issue = searchResults.nodes.find(
2209
2206
  (i) => i.identifier.toUpperCase() === issueIdentifier.toUpperCase()
2210
2207
  );
2211
2208
  if (!issue) return false;
2209
+ const team = await issue.team;
2210
+ if (!team) return false;
2212
2211
  const states = await team.states();
2213
2212
  const doneState = states.nodes.find((s) => s.type === "completed" && s.name === "Done");
2214
2213
  if (!doneState) return false;
@@ -2467,15 +2466,13 @@ async function updateLinearToInReview(apiKey, issueIdentifier, comment) {
2467
2466
  try {
2468
2467
  const { LinearClient: LinearClient2 } = await import("@linear/sdk");
2469
2468
  const client = new LinearClient2({ apiKey });
2470
- const me = await client.viewer;
2471
- const teams = await me.teams();
2472
- const team = teams.nodes[0];
2473
- if (!team) return false;
2474
- const issues = await team.issues({ first: 100 });
2475
- const issue = issues.nodes.find(
2469
+ const searchResults = await client.searchIssues(issueIdentifier, { first: 1 });
2470
+ const issue = searchResults.nodes.find(
2476
2471
  (i) => i.identifier.toUpperCase() === issueIdentifier.toUpperCase()
2477
2472
  );
2478
2473
  if (!issue) return false;
2474
+ const team = await issue.team;
2475
+ if (!team) return false;
2479
2476
  const states = await team.states();
2480
2477
  const targetStateName = getLinearStateName("in_review");
2481
2478
  const targetState = findLinearStateByName(states.nodes, targetStateName);
@@ -2557,7 +2554,7 @@ async function doneCommand(id, options = {}) {
2557
2554
  const issueId = id.replace(/^agent-/i, "").toUpperCase();
2558
2555
  const agentId = `agent-${issueId.toLowerCase()}`;
2559
2556
  if (!options.force) {
2560
- const { getAgentState: getAgentState2 } = await import("../agents-5HWTDR4S.js");
2557
+ const { getAgentState: getAgentState2 } = await import("../agents-QXVDAW2M.js");
2561
2558
  const agentState = getAgentState2(agentId);
2562
2559
  const workspacePath = agentState?.workspace;
2563
2560
  if (workspacePath && existsSync12(workspacePath)) {
@@ -2656,7 +2653,7 @@ async function doneCommand(id, options = {}) {
2656
2653
  console.log(chalk12.dim(" LINEAR_API_KEY not set - skipping status update"));
2657
2654
  }
2658
2655
  }
2659
- const { getAgentState: getAgentState2, saveAgentState: saveAgentState2 } = await import("../agents-5HWTDR4S.js");
2656
+ const { getAgentState: getAgentState2, saveAgentState: saveAgentState2 } = await import("../agents-QXVDAW2M.js");
2660
2657
  const existingState = getAgentState2(agentId);
2661
2658
  if (existingState) {
2662
2659
  existingState.status = "stopped";
@@ -3315,21 +3312,15 @@ async function planCommand(id, options = {}) {
3315
3312
  spinner.text = "Fetching issue from Linear...";
3316
3313
  const { LinearClient: LinearClient2 } = await import("@linear/sdk");
3317
3314
  const client = new LinearClient2({ apiKey });
3318
- const me = await client.viewer;
3319
- const teams = await me.teams();
3320
- const team = teams.nodes[0];
3321
- if (!team) {
3322
- spinner.fail("No Linear team found");
3323
- process.exit(1);
3324
- }
3325
- const searchResult = await team.issues({ first: 100 });
3326
- const issue = searchResult.nodes.find(
3315
+ const searchResults = await client.searchIssues(id, { first: 1 });
3316
+ const searchHit = searchResults.nodes.find(
3327
3317
  (i) => i.identifier.toUpperCase() === id.toUpperCase()
3328
3318
  );
3329
- if (!issue) {
3319
+ if (!searchHit) {
3330
3320
  spinner.fail(`Issue not found: ${id}`);
3331
3321
  process.exit(1);
3332
3322
  }
3323
+ const issue = await client.issue(searchHit.id);
3333
3324
  const state = await issue.state;
3334
3325
  const assignee = await issue.assignee;
3335
3326
  const project2 = await issue.project;
@@ -5201,7 +5192,7 @@ Previous state: ${issue.state}`
5201
5192
  console.log(chalk21.green(`\u2713 ${issue.identifier} reopened and ready for re-work`));
5202
5193
  console.log("");
5203
5194
  try {
5204
- const { getAgentState: getAgentState2 } = await import("../agents-5HWTDR4S.js");
5195
+ const { getAgentState: getAgentState2 } = await import("../agents-QXVDAW2M.js");
5205
5196
  const agentId = `agent-${id.toLowerCase()}`;
5206
5197
  const agentState = getAgentState2(agentId);
5207
5198
  const agentRunning = agentState?.status === "running" || agentState?.status === "starting";
@@ -5620,14 +5611,8 @@ async function syncToLinear(apiKey, issueId, targetState) {
5620
5611
  try {
5621
5612
  const { LinearClient: LinearClient2 } = await import("@linear/sdk");
5622
5613
  const client = new LinearClient2({ apiKey });
5623
- const me = await client.viewer;
5624
- const teams = await me.teams();
5625
- const team = teams.nodes[0];
5626
- if (!team) {
5627
- return { success: false, error: "No Linear team found" };
5628
- }
5629
- const issues = await team.issues({ first: 100 });
5630
- const issue = issues.nodes.find(
5614
+ const searchResults = await client.searchIssues(issueId, { first: 1 });
5615
+ const issue = searchResults.nodes.find(
5631
5616
  (i) => i.identifier.toUpperCase() === issueId.toUpperCase()
5632
5617
  );
5633
5618
  if (!issue) {
@@ -5635,6 +5620,10 @@ async function syncToLinear(apiKey, issueId, targetState) {
5635
5620
  }
5636
5621
  const currentState = await issue.state;
5637
5622
  const previousState = currentState?.type === "completed" ? "closed" : currentState?.type === "started" ? "in_progress" : "open";
5623
+ const team = await issue.team;
5624
+ if (!team) {
5625
+ return { success: false, error: "Could not resolve team from issue" };
5626
+ }
5638
5627
  const states = await team.states();
5639
5628
  let targetLinearState = null;
5640
5629
  switch (targetState) {
@@ -5839,14 +5828,8 @@ async function refreshFromLinear(apiKey, issueId) {
5839
5828
  try {
5840
5829
  const { LinearClient: LinearClient2 } = await import("@linear/sdk");
5841
5830
  const client = new LinearClient2({ apiKey });
5842
- const me = await client.viewer;
5843
- const teams = await me.teams();
5844
- const team = teams.nodes[0];
5845
- if (!team) {
5846
- return { success: false, error: "No Linear team found" };
5847
- }
5848
- const issues = await team.issues({ first: 100 });
5849
- const issue = issues.nodes.find(
5831
+ const searchResults = await client.searchIssues(issueId, { first: 1 });
5832
+ const issue = searchResults.nodes.find(
5850
5833
  (i) => i.identifier.toUpperCase() === issueId.toUpperCase()
5851
5834
  );
5852
5835
  if (!issue) {
@@ -6523,8 +6506,8 @@ async function verifyBranchMerged(ctx) {
6523
6506
  const branchName = `feature/${issueLower}`;
6524
6507
  try {
6525
6508
  try {
6526
- const { loadReviewStatuses: loadReviewStatuses3 } = await import("../review-status-J2YJGL3E.js");
6527
- const statuses = loadReviewStatuses3();
6509
+ const { loadReviewStatuses: loadReviewStatuses2 } = await import("../review-status-J2YJGL3E.js");
6510
+ const statuses = loadReviewStatuses2();
6528
6511
  const issueKey = ctx.issueId.toUpperCase();
6529
6512
  if (statuses[issueKey]?.mergeStatus === "merged") {
6530
6513
  return stepOk(step, ["Merge specialist confirmed merge completed"]);
@@ -6592,8 +6575,8 @@ async function clearReviewStatusStep(issueId) {
6592
6575
  const upperKey = issueId.toUpperCase();
6593
6576
  if (data[upperKey]) {
6594
6577
  delete data[upperKey];
6595
- const { writeFileSync: writeFileSync27 } = await import("fs");
6596
- writeFileSync27(statusFile, JSON.stringify(data, null, 2));
6578
+ const { writeFileSync: writeFileSync26 } = await import("fs");
6579
+ writeFileSync26(statusFile, JSON.stringify(data, null, 2));
6597
6580
  }
6598
6581
  }
6599
6582
  return stepOk(step, ["Review status cleared (direct)"]);
@@ -10849,7 +10832,7 @@ async function checkOrphanedReviewStatuses() {
10849
10832
  (h) => h.type === "review" && h.status === "passed"
10850
10833
  );
10851
10834
  const hasPassedTest = status.history?.some(
10852
- (h) => h.type === "test" && (h.status === "passed" || h.status === "failed")
10835
+ (h) => h.type === "test" && h.status === "passed"
10853
10836
  );
10854
10837
  const reviewAgentActive = activeReviewSessions.has(issueId.toUpperCase());
10855
10838
  if (status.reviewStatus === "reviewing" && !reviewAgentActive && !hasPassedReview) {
@@ -10885,7 +10868,7 @@ async function checkOrphanedReviewStatuses() {
10885
10868
  const { resolveProjectFromIssue: resolveProjectFromIssue2 } = await import("../projects-3CRF57ZU.js");
10886
10869
  const resolved = resolveProjectFromIssue2(issueId);
10887
10870
  if (resolved) {
10888
- const { spawnEphemeralSpecialist } = await import("../specialists-HTYYFXHQ.js");
10871
+ const { spawnEphemeralSpecialist } = await import("../specialists-XMFCFGYQ.js");
10889
10872
  const result = await spawnEphemeralSpecialist(resolved.projectKey, "test-agent", {
10890
10873
  issueId,
10891
10874
  workspace,
@@ -11287,7 +11270,7 @@ async function runPatrol() {
11287
11270
  statuses[issueId].mergeStatus = "merged";
11288
11271
  statuses[issueId].readyForMerge = false;
11289
11272
  writeFileSync19(REVIEW_STATUS_FILE, JSON.stringify(statuses, null, 2), "utf-8");
11290
- const { postMergeLifecycle } = await import("../merge-agent-WM7ZKUET.js");
11273
+ const { postMergeLifecycle } = await import("../merge-agent-O3TSBTLC.js");
11291
11274
  postMergeLifecycle(issueId, resolved.projectPath).catch(
11292
11275
  (err) => console.warn(`[deacon] postMergeLifecycle failed for ${issueId}: ${err}`)
11293
11276
  );
@@ -11738,6 +11721,10 @@ var CloisterService = class {
11738
11721
  console.log(`\u{1F514} Agent ${agentId} is suspended, skipping restart`);
11739
11722
  return;
11740
11723
  }
11724
+ if (runtimeState?.state === "stopped") {
11725
+ console.log(`\u{1F514} Agent ${agentId} runtime is stopped, skipping restart`);
11726
+ return;
11727
+ }
11741
11728
  const now = /* @__PURE__ */ new Date();
11742
11729
  this.deathTimestamps.push(now);
11743
11730
  this.checkForMassDeaths();
@@ -13049,24 +13036,8 @@ function confirm2(question) {
13049
13036
 
13050
13037
  // src/cli/commands/specialists/done.ts
13051
13038
  init_esm_shims();
13039
+ init_review_status();
13052
13040
  import chalk45 from "chalk";
13053
- import { existsSync as existsSync44, readFileSync as readFileSync38, writeFileSync as writeFileSync24 } from "fs";
13054
- import { join as join43 } from "path";
13055
- import { homedir as homedir20 } from "os";
13056
- var REVIEW_STATUS_FILE3 = join43(homedir20(), ".panopticon", "review-status.json");
13057
- function loadReviewStatuses2() {
13058
- try {
13059
- if (existsSync44(REVIEW_STATUS_FILE3)) {
13060
- return JSON.parse(readFileSync38(REVIEW_STATUS_FILE3, "utf-8"));
13061
- }
13062
- } catch (error) {
13063
- console.error(chalk45.yellow("Warning: Could not load review statuses"));
13064
- }
13065
- return {};
13066
- }
13067
- function saveReviewStatuses2(statuses) {
13068
- writeFileSync24(REVIEW_STATUS_FILE3, JSON.stringify(statuses, null, 2));
13069
- }
13070
13041
  async function doneCommand2(specialist, issueId, options) {
13071
13042
  const validSpecialists = ["review", "test", "merge"];
13072
13043
  if (!validSpecialists.includes(specialist)) {
@@ -13084,57 +13055,39 @@ async function doneCommand2(specialist, issueId, options) {
13084
13055
  process.exit(1);
13085
13056
  }
13086
13057
  const normalizedIssueId = issueId.toUpperCase();
13087
- const statuses = loadReviewStatuses2();
13088
- let status = statuses[normalizedIssueId];
13089
- if (!status) {
13090
- status = {
13091
- issueId: normalizedIssueId,
13092
- reviewStatus: "pending",
13093
- testStatus: "pending",
13094
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
13095
- readyForMerge: false
13096
- };
13097
- }
13058
+ const update = {};
13098
13059
  switch (specialist) {
13099
13060
  case "review":
13100
- status.reviewStatus = options.status;
13101
- if (options.notes) {
13102
- status.reviewNotes = options.notes;
13103
- }
13061
+ update.reviewStatus = options.status;
13062
+ if (options.notes) update.reviewNotes = options.notes;
13104
13063
  console.log(chalk45.green(`\u2713 Review ${options.status} for ${normalizedIssueId}`));
13105
13064
  if (options.status === "passed") {
13106
13065
  console.log(chalk45.dim(" Test agent can now proceed"));
13107
13066
  }
13108
13067
  break;
13109
13068
  case "test":
13110
- status.testStatus = options.status;
13111
- if (options.notes) {
13112
- status.testNotes = options.notes;
13113
- }
13114
- if (options.status === "passed" && status.reviewStatus === "passed") {
13115
- status.readyForMerge = true;
13116
- console.log(chalk45.green(`\u2713 Tests ${options.status} for ${normalizedIssueId}`));
13117
- console.log(chalk45.green("\u2713 Ready for merge!"));
13118
- } else if (options.status === "passed") {
13069
+ update.testStatus = options.status;
13070
+ if (options.notes) update.testNotes = options.notes;
13071
+ if (options.status === "passed") {
13119
13072
  console.log(chalk45.green(`\u2713 Tests ${options.status} for ${normalizedIssueId}`));
13120
13073
  } else {
13121
13074
  console.log(chalk45.yellow(`\u2717 Tests ${options.status} for ${normalizedIssueId}`));
13122
- status.readyForMerge = false;
13123
13075
  }
13124
13076
  break;
13125
13077
  case "merge":
13126
- status.mergeStatus = options.status === "passed" ? "merged" : "failed";
13078
+ update.mergeStatus = options.status === "passed" ? "merged" : "failed";
13127
13079
  if (options.status === "passed") {
13080
+ update.readyForMerge = false;
13128
13081
  console.log(chalk45.green(`\u2713 Merge completed for ${normalizedIssueId}`));
13129
- status.readyForMerge = false;
13130
13082
  } else {
13131
13083
  console.log(chalk45.red(`\u2717 Merge failed for ${normalizedIssueId}`));
13132
13084
  }
13133
13085
  break;
13134
13086
  }
13135
- status.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
13136
- statuses[normalizedIssueId] = status;
13137
- saveReviewStatuses2(statuses);
13087
+ const status = setReviewStatus(normalizedIssueId, update);
13088
+ if (specialist === "test" && status.readyForMerge) {
13089
+ console.log(chalk45.green("\u2713 Ready for merge!"));
13090
+ }
13138
13091
  if (options.notes) {
13139
13092
  console.log(chalk45.dim(` Notes: ${options.notes}`));
13140
13093
  }
@@ -13166,13 +13119,13 @@ function formatStatus(status) {
13166
13119
 
13167
13120
  // src/cli/commands/specialists/logs.ts
13168
13121
  init_esm_shims();
13169
- import { existsSync as existsSync45 } from "fs";
13122
+ import { existsSync as existsSync44 } from "fs";
13170
13123
  import { exec as exec15 } from "child_process";
13171
13124
  import { promisify as promisify15 } from "util";
13172
13125
  var execAsync15 = promisify15(exec15);
13173
13126
  async function listLogsCommand(project2, type, options) {
13174
13127
  try {
13175
- const { listRunLogs } = await import("../specialist-logs-T5GW7CSU.js");
13128
+ const { listRunLogs } = await import("../specialist-logs-GFKUXCFG.js");
13176
13129
  const limit = options.limit ? parseInt(options.limit) : 10;
13177
13130
  const runs = listRunLogs(project2, type, { limit });
13178
13131
  if (options.json) {
@@ -13217,7 +13170,7 @@ View a specific run: pan specialists logs ${project2} ${type} <runId>
13217
13170
  }
13218
13171
  async function viewLogCommand(project2, type, runId, options) {
13219
13172
  try {
13220
- const { getRunLog, parseLogMetadata, getRunLogPath } = await import("../specialist-logs-T5GW7CSU.js");
13173
+ const { getRunLog, parseLogMetadata, getRunLogPath } = await import("../specialist-logs-GFKUXCFG.js");
13221
13174
  const content = getRunLog(project2, type, runId);
13222
13175
  if (!content) {
13223
13176
  console.error(`\u274C Run log not found: ${runId}`);
@@ -13241,15 +13194,15 @@ async function viewLogCommand(project2, type, runId, options) {
13241
13194
  }
13242
13195
  async function tailLogCommand(project2, type) {
13243
13196
  try {
13244
- const { getRunLogPath } = await import("../specialist-logs-T5GW7CSU.js");
13245
- const { getProjectSpecialistMetadata } = await import("../specialists-HTYYFXHQ.js");
13197
+ const { getRunLogPath } = await import("../specialist-logs-GFKUXCFG.js");
13198
+ const { getProjectSpecialistMetadata } = await import("../specialists-XMFCFGYQ.js");
13246
13199
  const metadata = getProjectSpecialistMetadata(project2, type);
13247
13200
  if (!metadata.currentRun) {
13248
13201
  console.error(`\u274C No active run for ${project2}/${type}`);
13249
13202
  process.exit(1);
13250
13203
  }
13251
13204
  const logPath = getRunLogPath(project2, type, metadata.currentRun);
13252
- if (!existsSync45(logPath)) {
13205
+ if (!existsSync44(logPath)) {
13253
13206
  console.error(`\u274C Log file not found: ${logPath}`);
13254
13207
  process.exit(1);
13255
13208
  }
@@ -13311,7 +13264,7 @@ async function cleanupLogsCommand(projectOrAll, type, options) {
13311
13264
  console.log(" Use --force to confirm.");
13312
13265
  process.exit(1);
13313
13266
  }
13314
- const { cleanupAllLogs } = await import("../specialist-logs-T5GW7CSU.js");
13267
+ const { cleanupAllLogs } = await import("../specialist-logs-GFKUXCFG.js");
13315
13268
  console.log("\u{1F9F9} Cleaning up old logs for all projects...\n");
13316
13269
  const results = cleanupAllLogs();
13317
13270
  console.log(`
@@ -13338,7 +13291,7 @@ async function cleanupLogsCommand(projectOrAll, type, options) {
13338
13291
  console.log(" Use --force to confirm.");
13339
13292
  process.exit(1);
13340
13293
  }
13341
- const { cleanupOldLogs } = await import("../specialist-logs-T5GW7CSU.js");
13294
+ const { cleanupOldLogs } = await import("../specialist-logs-GFKUXCFG.js");
13342
13295
  const { getSpecialistRetention } = await import("../projects-3CRF57ZU.js");
13343
13296
  const retention = getSpecialistRetention(projectOrAll);
13344
13297
  console.log(`\u{1F9F9} Cleaning up old logs for ${projectOrAll}/${type}...`);
@@ -13377,9 +13330,9 @@ import ora19 from "ora";
13377
13330
  // src/lib/convoy.ts
13378
13331
  init_esm_shims();
13379
13332
  init_tmux();
13380
- import { existsSync as existsSync46, mkdirSync as mkdirSync22, writeFileSync as writeFileSync25, readFileSync as readFileSync40, readdirSync as readdirSync19 } from "fs";
13381
- import { join as join44 } from "path";
13382
- import { homedir as homedir21 } from "os";
13333
+ import { existsSync as existsSync45, mkdirSync as mkdirSync22, writeFileSync as writeFileSync24, readFileSync as readFileSync39, readdirSync as readdirSync19 } from "fs";
13334
+ import { join as join43 } from "path";
13335
+ import { homedir as homedir20 } from "os";
13383
13336
  import { exec as exec16 } from "child_process";
13384
13337
  import { promisify as promisify16 } from "util";
13385
13338
  import { parse as parseYaml } from "yaml";
@@ -13487,25 +13440,25 @@ function getExecutionOrder(template) {
13487
13440
  init_paths();
13488
13441
  init_work_type_router();
13489
13442
  var execAsync16 = promisify16(exec16);
13490
- var CONVOY_DIR = join44(homedir21(), ".panopticon", "convoys");
13443
+ var CONVOY_DIR = join43(homedir20(), ".panopticon", "convoys");
13491
13444
  function getConvoyStateFile(convoyId) {
13492
- return join44(CONVOY_DIR, `${convoyId}.json`);
13445
+ return join43(CONVOY_DIR, `${convoyId}.json`);
13493
13446
  }
13494
13447
  function getConvoyOutputDir(convoyId, template) {
13495
13448
  const baseDir = template.config?.outputDir || ".panopticon/convoy-output";
13496
- return join44(process.cwd(), baseDir, convoyId);
13449
+ return join43(process.cwd(), baseDir, convoyId);
13497
13450
  }
13498
13451
  function saveConvoyState(state) {
13499
13452
  mkdirSync22(CONVOY_DIR, { recursive: true });
13500
- writeFileSync25(getConvoyStateFile(state.id), JSON.stringify(state, null, 2));
13453
+ writeFileSync24(getConvoyStateFile(state.id), JSON.stringify(state, null, 2));
13501
13454
  }
13502
13455
  function loadConvoyState(convoyId) {
13503
13456
  const stateFile = getConvoyStateFile(convoyId);
13504
- if (!existsSync46(stateFile)) {
13457
+ if (!existsSync45(stateFile)) {
13505
13458
  return void 0;
13506
13459
  }
13507
13460
  try {
13508
- const content = readFileSync40(stateFile, "utf-8");
13461
+ const content = readFileSync39(stateFile, "utf-8");
13509
13462
  return JSON.parse(content);
13510
13463
  } catch {
13511
13464
  return void 0;
@@ -13515,7 +13468,7 @@ function getConvoyStatus(convoyId) {
13515
13468
  return loadConvoyState(convoyId);
13516
13469
  }
13517
13470
  function listConvoys(filter) {
13518
- if (!existsSync46(CONVOY_DIR)) {
13471
+ if (!existsSync45(CONVOY_DIR)) {
13519
13472
  return [];
13520
13473
  }
13521
13474
  const files = readdirSync19(CONVOY_DIR).filter((f) => f.endsWith(".json"));
@@ -13534,10 +13487,10 @@ function listConvoys(filter) {
13534
13487
  );
13535
13488
  }
13536
13489
  function parseAgentTemplate(templatePath) {
13537
- if (!existsSync46(templatePath)) {
13490
+ if (!existsSync45(templatePath)) {
13538
13491
  throw new Error(`Agent template not found: ${templatePath}`);
13539
13492
  }
13540
- const content = readFileSync40(templatePath, "utf-8");
13493
+ const content = readFileSync39(templatePath, "utf-8");
13541
13494
  const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---\n([\s\S]*)$/);
13542
13495
  if (!frontmatterMatch) {
13543
13496
  throw new Error(`Invalid agent template format (missing frontmatter): ${templatePath}`);
@@ -13563,7 +13516,7 @@ function mapConvoyRoleToWorkType(role) {
13563
13516
  }
13564
13517
  async function spawnConvoyAgent(convoy, agent, agentState, context) {
13565
13518
  const { role, subagent } = agent;
13566
- const templatePath = join44(AGENTS_DIR, `${subagent}.md`);
13519
+ const templatePath = join43(AGENTS_DIR, `${subagent}.md`);
13567
13520
  const template = parseAgentTemplate(templatePath);
13568
13521
  let model = template.model;
13569
13522
  try {
@@ -13602,8 +13555,8 @@ ${context.issueId ? `**Issue ID**: ${context.issueId}` : ""}
13602
13555
  `;
13603
13556
  prompt = contextInstructions + prompt;
13604
13557
  mkdirSync22(convoy.outputDir, { recursive: true });
13605
- const promptFile = join44(convoy.outputDir, `${role}-prompt.md`);
13606
- writeFileSync25(promptFile, prompt);
13558
+ const promptFile = join43(convoy.outputDir, `${role}-prompt.md`);
13559
+ writeFileSync24(promptFile, prompt);
13607
13560
  const claudeCmd = `claude --dangerously-skip-permissions --model ${model}`;
13608
13561
  createSession(agentState.tmuxSession, convoy.context.projectPath, claudeCmd, {
13609
13562
  env: {
@@ -13641,7 +13594,7 @@ async function startConvoy(templateName, context) {
13641
13594
  };
13642
13595
  for (const agent of template.agents) {
13643
13596
  const tmuxSession = `${convoyId}-${agent.role}`;
13644
- const outputFile = join44(outputDir, `${agent.role}.md`);
13597
+ const outputFile = join43(outputDir, `${agent.role}.md`);
13645
13598
  state.agents.push({
13646
13599
  role: agent.role,
13647
13600
  subagent: agent.subagent,
@@ -13676,8 +13629,8 @@ async function executePhase(convoy, template, phaseAgents, context) {
13676
13629
  const agentContext = { ...context };
13677
13630
  for (const depRole of deps) {
13678
13631
  const depAgent = convoy.agents.find((a) => a.role === depRole);
13679
- if (depAgent?.outputFile && existsSync46(depAgent.outputFile)) {
13680
- agentContext[`${depRole}_output`] = readFileSync40(depAgent.outputFile, "utf-8");
13632
+ if (depAgent?.outputFile && existsSync45(depAgent.outputFile)) {
13633
+ agentContext[`${depRole}_output`] = readFileSync39(depAgent.outputFile, "utf-8");
13681
13634
  }
13682
13635
  }
13683
13636
  spawnPromises.push(spawnConvoyAgent(convoy, agent, agentState, agentContext));
@@ -13740,7 +13693,7 @@ function updateAgentStatuses(convoy) {
13740
13693
  agent.status = "completed";
13741
13694
  agent.completedAt = (/* @__PURE__ */ new Date()).toISOString();
13742
13695
  updated = true;
13743
- if (agent.outputFile && existsSync46(agent.outputFile)) {
13696
+ if (agent.outputFile && existsSync45(agent.outputFile)) {
13744
13697
  agent.exitCode = 0;
13745
13698
  } else {
13746
13699
  agent.exitCode = 1;
@@ -13986,30 +13939,30 @@ function registerConvoyCommands(program2) {
13986
13939
  init_esm_shims();
13987
13940
  init_projects();
13988
13941
  import chalk50 from "chalk";
13989
- import { existsSync as existsSync47, readFileSync as readFileSync41, symlinkSync as symlinkSync2, mkdirSync as mkdirSync23, readdirSync as readdirSync20, statSync as statSync10 } from "fs";
13990
- import { join as join45, resolve as resolve2, dirname as dirname13 } from "path";
13942
+ import { existsSync as existsSync46, readFileSync as readFileSync40, symlinkSync as symlinkSync2, mkdirSync as mkdirSync23, readdirSync as readdirSync20, statSync as statSync10 } from "fs";
13943
+ import { join as join44, resolve as resolve2, dirname as dirname13 } from "path";
13991
13944
  import { fileURLToPath as fileURLToPath4 } from "url";
13992
13945
  var __filename5 = fileURLToPath4(import.meta.url);
13993
13946
  var __dirname5 = dirname13(__filename5);
13994
- var BUNDLED_HOOKS_DIR = join45(__dirname5, "..", "..", "scripts", "git-hooks");
13947
+ var BUNDLED_HOOKS_DIR = join44(__dirname5, "..", "..", "scripts", "git-hooks");
13995
13948
  function installGitHooks(gitDir) {
13996
- const hooksTarget = join45(gitDir, "hooks");
13949
+ const hooksTarget = join44(gitDir, "hooks");
13997
13950
  let installed = 0;
13998
- if (!existsSync47(hooksTarget)) {
13951
+ if (!existsSync46(hooksTarget)) {
13999
13952
  mkdirSync23(hooksTarget, { recursive: true });
14000
13953
  }
14001
- if (!existsSync47(BUNDLED_HOOKS_DIR)) {
13954
+ if (!existsSync46(BUNDLED_HOOKS_DIR)) {
14002
13955
  return 0;
14003
13956
  }
14004
13957
  try {
14005
13958
  const hooks = readdirSync20(BUNDLED_HOOKS_DIR).filter((f) => {
14006
- const p = join45(BUNDLED_HOOKS_DIR, f);
14007
- return existsSync47(p) && statSync10(p).isFile();
13959
+ const p = join44(BUNDLED_HOOKS_DIR, f);
13960
+ return existsSync46(p) && statSync10(p).isFile();
14008
13961
  });
14009
13962
  for (const hook of hooks) {
14010
- const source = join45(BUNDLED_HOOKS_DIR, hook);
14011
- const target = join45(hooksTarget, hook);
14012
- if (existsSync47(target)) {
13963
+ const source = join44(BUNDLED_HOOKS_DIR, hook);
13964
+ const target = join44(hooksTarget, hook);
13965
+ if (existsSync46(target)) {
14013
13966
  try {
14014
13967
  const { readlinkSync: readlinkSync2 } = __require("fs");
14015
13968
  if (readlinkSync2(target) === source) {
@@ -14018,7 +13971,7 @@ function installGitHooks(gitDir) {
14018
13971
  } catch {
14019
13972
  }
14020
13973
  }
14021
- if (existsSync47(target)) {
13974
+ if (existsSync46(target)) {
14022
13975
  const { renameSync: renameSync4 } = __require("fs");
14023
13976
  renameSync4(target, `${target}.backup`);
14024
13977
  }
@@ -14031,7 +13984,7 @@ function installGitHooks(gitDir) {
14031
13984
  }
14032
13985
  async function projectAddCommand(projectPath, options = {}) {
14033
13986
  const fullPath = resolve2(projectPath);
14034
- if (!existsSync47(fullPath)) {
13987
+ if (!existsSync46(fullPath)) {
14035
13988
  console.log(chalk50.red(`Path does not exist: ${fullPath}`));
14036
13989
  return;
14037
13990
  }
@@ -14046,9 +13999,9 @@ async function projectAddCommand(projectPath, options = {}) {
14046
13999
  }
14047
14000
  let linearTeam = options.linearTeam;
14048
14001
  if (!linearTeam) {
14049
- const projectToml = join45(fullPath, ".panopticon", "project.toml");
14050
- if (existsSync47(projectToml)) {
14051
- const content = readFileSync41(projectToml, "utf-8");
14002
+ const projectToml = join44(fullPath, ".panopticon", "project.toml");
14003
+ if (existsSync46(projectToml)) {
14004
+ const content = readFileSync40(projectToml, "utf-8");
14052
14005
  const match = content.match(/team\s*=\s*"([^"]+)"/);
14053
14006
  if (match) linearTeam = match[1];
14054
14007
  }
@@ -14074,19 +14027,19 @@ async function projectAddCommand(projectPath, options = {}) {
14074
14027
  console.log(chalk50.dim(` Rally project: ${options.rallyProject}`));
14075
14028
  }
14076
14029
  console.log("");
14077
- const hasDevcontainer = existsSync47(join45(fullPath, ".devcontainer"));
14078
- const hasInfra = existsSync47(join45(fullPath, "infra"));
14079
- const hasDevcontainerTemplate = existsSync47(join45(fullPath, "infra", ".devcontainer-template")) || existsSync47(join45(fullPath, ".devcontainer-template"));
14080
- const hasRootGit = existsSync47(join45(fullPath, ".git"));
14030
+ const hasDevcontainer = existsSync46(join44(fullPath, ".devcontainer"));
14031
+ const hasInfra = existsSync46(join44(fullPath, "infra"));
14032
+ const hasDevcontainerTemplate = existsSync46(join44(fullPath, "infra", ".devcontainer-template")) || existsSync46(join44(fullPath, ".devcontainer-template"));
14033
+ const hasRootGit = existsSync46(join44(fullPath, ".git"));
14081
14034
  const subRepos = [];
14082
14035
  if (!hasRootGit) {
14083
14036
  const { readdirSync: readdirSync22, statSync: statSync12 } = await import("fs");
14084
14037
  try {
14085
14038
  const entries = readdirSync22(fullPath);
14086
14039
  for (const entry of entries) {
14087
- const entryPath = join45(fullPath, entry);
14040
+ const entryPath = join44(fullPath, entry);
14088
14041
  try {
14089
- if (statSync12(entryPath).isDirectory() && existsSync47(join45(entryPath, ".git"))) {
14042
+ if (statSync12(entryPath).isDirectory() && existsSync46(join44(entryPath, ".git"))) {
14090
14043
  subRepos.push(entry);
14091
14044
  }
14092
14045
  } catch {
@@ -14103,13 +14056,13 @@ async function projectAddCommand(projectPath, options = {}) {
14103
14056
  }
14104
14057
  let hooksInstalled = 0;
14105
14058
  if (hasRootGit) {
14106
- hooksInstalled = installGitHooks(join45(fullPath, ".git"));
14059
+ hooksInstalled = installGitHooks(join44(fullPath, ".git"));
14107
14060
  if (hooksInstalled > 0) {
14108
14061
  console.log(chalk50.green(`\u2713 Installed ${hooksInstalled} git hook(s) for branch protection`));
14109
14062
  }
14110
14063
  } else if (isPolyrepo) {
14111
14064
  for (const repo of subRepos) {
14112
- const count = installGitHooks(join45(fullPath, repo, ".git"));
14065
+ const count = installGitHooks(join44(fullPath, repo, ".git"));
14113
14066
  hooksInstalled += count;
14114
14067
  }
14115
14068
  if (hooksInstalled > 0) {
@@ -14181,7 +14134,7 @@ async function projectListCommand(options = {}) {
14181
14134
  }
14182
14135
  console.log(chalk50.bold("\nRegistered Projects:\n"));
14183
14136
  for (const { key, config: config2 } of projects) {
14184
- const exists = existsSync47(config2.path);
14137
+ const exists = existsSync46(config2.path);
14185
14138
  const statusIcon = exists ? chalk50.green("\u2713") : chalk50.red("\u2717");
14186
14139
  console.log(`${statusIcon} ${chalk50.bold(config2.name)} ${chalk50.dim(`(${key})`)}`);
14187
14140
  console.log(` ${chalk50.dim(config2.path)}`);
@@ -14215,7 +14168,7 @@ async function projectRemoveCommand(nameOrPath) {
14215
14168
  console.log(chalk50.dim(`Use 'pan project list' to see registered projects.`));
14216
14169
  }
14217
14170
  async function projectInitCommand() {
14218
- if (existsSync47(PROJECTS_CONFIG_FILE)) {
14171
+ if (existsSync46(PROJECTS_CONFIG_FILE)) {
14219
14172
  console.log(chalk50.yellow(`Config already exists: ${PROJECTS_CONFIG_FILE}`));
14220
14173
  return;
14221
14174
  }
@@ -14249,7 +14202,7 @@ async function projectShowCommand(keyOrName) {
14249
14202
  console.log(chalk50.dim(`Use 'pan project list' to see registered projects.`));
14250
14203
  process.exit(1);
14251
14204
  }
14252
- const pathExists = existsSync47(found.path);
14205
+ const pathExists = existsSync46(found.path);
14253
14206
  const pathStatus = pathExists ? chalk50.green("\u2713") : chalk50.red("\u2717");
14254
14207
  console.log(chalk50.bold(`
14255
14208
  Project: ${foundKey}
@@ -14281,10 +14234,10 @@ Project: ${foundKey}
14281
14234
  init_esm_shims();
14282
14235
  init_paths();
14283
14236
  import chalk51 from "chalk";
14284
- import { existsSync as existsSync48, readdirSync as readdirSync21, readFileSync as readFileSync42 } from "fs";
14237
+ import { existsSync as existsSync47, readdirSync as readdirSync21, readFileSync as readFileSync41 } from "fs";
14285
14238
  import { execSync as execSync6 } from "child_process";
14286
- import { homedir as homedir22 } from "os";
14287
- import { join as join46 } from "path";
14239
+ import { homedir as homedir21 } from "os";
14240
+ import { join as join45 } from "path";
14288
14241
  function checkCommand3(cmd) {
14289
14242
  try {
14290
14243
  execSync6(`which ${cmd}`, { encoding: "utf-8", stdio: "pipe" });
@@ -14294,10 +14247,10 @@ function checkCommand3(cmd) {
14294
14247
  }
14295
14248
  }
14296
14249
  function checkDirectory(path) {
14297
- return existsSync48(path);
14250
+ return existsSync47(path);
14298
14251
  }
14299
14252
  function countItems(path) {
14300
- if (!existsSync48(path)) return 0;
14253
+ if (!existsSync47(path)) return 0;
14301
14254
  try {
14302
14255
  return readdirSync21(path).length;
14303
14256
  } catch {
@@ -14348,8 +14301,8 @@ async function doctorCommand() {
14348
14301
  }
14349
14302
  }
14350
14303
  if (checkDirectory(CLAUDE_DIR)) {
14351
- const skillsCount = countItems(join46(CLAUDE_DIR, "skills"));
14352
- const commandsCount = countItems(join46(CLAUDE_DIR, "commands"));
14304
+ const skillsCount = countItems(join45(CLAUDE_DIR, "skills"));
14305
+ const commandsCount = countItems(join45(CLAUDE_DIR, "commands"));
14353
14306
  checks.push({
14354
14307
  name: "Claude Code Skills",
14355
14308
  status: skillsCount > 0 ? "ok" : "warn",
@@ -14370,8 +14323,8 @@ async function doctorCommand() {
14370
14323
  fix: "Install Claude Code first"
14371
14324
  });
14372
14325
  }
14373
- const envFile = join46(homedir22(), ".panopticon.env");
14374
- if (existsSync48(envFile)) {
14326
+ const envFile = join45(homedir21(), ".panopticon.env");
14327
+ if (existsSync47(envFile)) {
14375
14328
  checks.push({ name: "Config File", status: "ok", message: "~/.panopticon.env exists" });
14376
14329
  } else {
14377
14330
  checks.push({
@@ -14383,8 +14336,8 @@ async function doctorCommand() {
14383
14336
  }
14384
14337
  if (process.env.LINEAR_API_KEY) {
14385
14338
  checks.push({ name: "LINEAR_API_KEY", status: "ok", message: "Set in environment" });
14386
- } else if (existsSync48(envFile)) {
14387
- const content = readFileSync42(envFile, "utf-8");
14339
+ } else if (existsSync47(envFile)) {
14340
+ const content = readFileSync41(envFile, "utf-8");
14388
14341
  if (content.includes("LINEAR_API_KEY")) {
14389
14342
  checks.push({ name: "LINEAR_API_KEY", status: "ok", message: "Set in config file" });
14390
14343
  } else {
@@ -14452,15 +14405,15 @@ init_esm_shims();
14452
14405
  init_config();
14453
14406
  import { execSync as execSync7 } from "child_process";
14454
14407
  import chalk52 from "chalk";
14455
- import { readFileSync as readFileSync43 } from "fs";
14408
+ import { readFileSync as readFileSync42 } from "fs";
14456
14409
  import { fileURLToPath as fileURLToPath5 } from "url";
14457
- import { dirname as dirname14, join as join47 } from "path";
14410
+ import { dirname as dirname14, join as join46 } from "path";
14458
14411
  function getCurrentVersion() {
14459
14412
  try {
14460
14413
  const __filename6 = fileURLToPath5(import.meta.url);
14461
14414
  const __dirname6 = dirname14(__filename6);
14462
- const pkgPath = join47(__dirname6, "..", "..", "..", "package.json");
14463
- const pkg = JSON.parse(readFileSync43(pkgPath, "utf-8"));
14415
+ const pkgPath = join46(__dirname6, "..", "..", "..", "package.json");
14416
+ const pkg = JSON.parse(readFileSync42(pkgPath, "utf-8"));
14464
14417
  return pkg.version;
14465
14418
  } catch {
14466
14419
  return "unknown";
@@ -14546,8 +14499,8 @@ init_esm_shims();
14546
14499
  init_projects();
14547
14500
  import chalk53 from "chalk";
14548
14501
  import ora21 from "ora";
14549
- import { existsSync as existsSync49, readFileSync as readFileSync44, writeFileSync as writeFileSync26, mkdirSync as mkdirSync24, statSync as statSync11 } from "fs";
14550
- import { join as join48, dirname as dirname15 } from "path";
14502
+ import { existsSync as existsSync48, readFileSync as readFileSync43, writeFileSync as writeFileSync25, mkdirSync as mkdirSync24, statSync as statSync11 } from "fs";
14503
+ import { join as join47, dirname as dirname15 } from "path";
14551
14504
  import { exec as exec17 } from "child_process";
14552
14505
  import { promisify as promisify17 } from "util";
14553
14506
  var execAsync17 = promisify17(exec17);
@@ -14609,9 +14562,9 @@ async function snapshotCommand(options) {
14609
14562
  `));
14610
14563
  return;
14611
14564
  }
14612
- const outputPath = options.output || dbConfig.seed_file || join48(projectConfig.path, "infra", "seed", "seed.sql");
14565
+ const outputPath = options.output || dbConfig.seed_file || join47(projectConfig.path, "infra", "seed", "seed.sql");
14613
14566
  const outputDir = dirname15(outputPath);
14614
- if (!existsSync49(outputDir)) {
14567
+ if (!existsSync48(outputDir)) {
14615
14568
  mkdirSync24(outputDir, { recursive: true });
14616
14569
  }
14617
14570
  spinner.text = "Running snapshot command...";
@@ -14634,8 +14587,8 @@ async function snapshotCommand(options) {
14634
14587
  try {
14635
14588
  await execAsync17(fullCmd, { timeout: 3e5 });
14636
14589
  } catch (error) {
14637
- if (existsSync49(outputPath)) {
14638
- const content2 = readFileSync44(outputPath, "utf-8");
14590
+ if (existsSync48(outputPath)) {
14591
+ const content2 = readFileSync43(outputPath, "utf-8");
14639
14592
  if (content2.includes("PostgreSQL database dump")) {
14640
14593
  spinner.warn("Snapshot completed with warnings (stderr captured)");
14641
14594
  console.log(chalk53.dim(" Run `pan db clean` to remove stderr noise from the file"));
@@ -14648,7 +14601,7 @@ async function snapshotCommand(options) {
14648
14601
  return;
14649
14602
  }
14650
14603
  }
14651
- const content = readFileSync44(outputPath, "utf-8");
14604
+ const content = readFileSync43(outputPath, "utf-8");
14652
14605
  if (content.includes("Defaulted container") || content.includes("Unable to use a TTY")) {
14653
14606
  spinner.text = "Cleaning kubectl output from snapshot...";
14654
14607
  await cleanFile(outputPath);
@@ -14680,14 +14633,14 @@ async function seedCommand(workspaceOrIssue, options) {
14680
14633
  spinner.fail("Could not find project workspace configuration");
14681
14634
  return;
14682
14635
  }
14683
- const workspacePath = join48(projectConfig.path, projectConfig.workspace.workspaces_dir || "workspaces", folderName);
14684
- if (!existsSync49(workspacePath)) {
14636
+ const workspacePath = join47(projectConfig.path, projectConfig.workspace.workspaces_dir || "workspaces", folderName);
14637
+ if (!existsSync48(workspacePath)) {
14685
14638
  spinner.fail(`Workspace not found: ${workspacePath}`);
14686
14639
  return;
14687
14640
  }
14688
14641
  const dbConfig = projectConfig.workspace.database;
14689
14642
  const seedFile = options.file || dbConfig?.seed_file;
14690
- if (!seedFile || !existsSync49(seedFile)) {
14643
+ if (!seedFile || !existsSync48(seedFile)) {
14691
14644
  spinner.fail(`Seed file not found: ${seedFile || "(not configured)"}`);
14692
14645
  console.log(chalk53.dim("\nConfigure seed_file in projects.yaml or use --file"));
14693
14646
  return;
@@ -14829,11 +14782,11 @@ async function statusCommand5(workspaceOrIssue) {
14829
14782
  async function cleanCommand(file, options) {
14830
14783
  const spinner = ora21("Cleaning database dump file...").start();
14831
14784
  try {
14832
- if (!existsSync49(file)) {
14785
+ if (!existsSync48(file)) {
14833
14786
  spinner.fail(`File not found: ${file}`);
14834
14787
  return;
14835
14788
  }
14836
- const content = readFileSync44(file, "utf-8");
14789
+ const content = readFileSync43(file, "utf-8");
14837
14790
  const lines = content.split("\n");
14838
14791
  const patternsToRemove = [
14839
14792
  /^Defaulted container/,
@@ -14893,7 +14846,7 @@ async function cleanCommand(file, options) {
14893
14846
  return;
14894
14847
  }
14895
14848
  const outputPath = options.output || file;
14896
- writeFileSync26(outputPath, cleanedContent);
14849
+ writeFileSync25(outputPath, cleanedContent);
14897
14850
  spinner.succeed(`Cleaned ${removedLines} lines`);
14898
14851
  console.log(chalk53.dim(` Output: ${outputPath}`));
14899
14852
  console.log(chalk53.dim(` Original: ${lines.length} lines`));
@@ -14903,7 +14856,7 @@ async function cleanCommand(file, options) {
14903
14856
  }
14904
14857
  }
14905
14858
  async function cleanFile(filePath) {
14906
- const content = readFileSync44(filePath, "utf-8");
14859
+ const content = readFileSync43(filePath, "utf-8");
14907
14860
  const lines = content.split("\n");
14908
14861
  let startIndex = 0;
14909
14862
  for (let i = 0; i < lines.length; i++) {
@@ -14923,7 +14876,7 @@ async function cleanFile(filePath) {
14923
14876
  /^error: timed out waiting/
14924
14877
  ];
14925
14878
  const cleanedLines = lines.slice(startIndex).filter((line) => !patternsToRemove.some((p) => p.test(line)));
14926
- writeFileSync26(filePath, cleanedLines.join("\n"));
14879
+ writeFileSync25(filePath, cleanedLines.join("\n"));
14927
14880
  }
14928
14881
  async function configCommand(project2) {
14929
14882
  const projects = loadFullProjects();
@@ -14957,7 +14910,7 @@ async function configCommand(project2) {
14957
14910
  return;
14958
14911
  }
14959
14912
  if (dbConfig.seed_file) {
14960
- const exists = existsSync49(dbConfig.seed_file);
14913
+ const exists = existsSync48(dbConfig.seed_file);
14961
14914
  console.log(` Seed file: ${dbConfig.seed_file}`);
14962
14915
  console.log(chalk53.dim(` Status: ${exists ? chalk53.green("exists") : chalk53.red("not found")}`));
14963
14916
  if (exists) {
@@ -14986,8 +14939,8 @@ async function configCommand(project2) {
14986
14939
  init_esm_shims();
14987
14940
  import chalk54 from "chalk";
14988
14941
  import ora22 from "ora";
14989
- import { existsSync as existsSync50, readFileSync as readFileSync45 } from "fs";
14990
- import { join as join49 } from "path";
14942
+ import { existsSync as existsSync49, readFileSync as readFileSync44 } from "fs";
14943
+ import { join as join48 } from "path";
14991
14944
  import { exec as exec18, execSync as execSync8 } from "child_process";
14992
14945
  import { promisify as promisify18 } from "util";
14993
14946
  import { platform } from "os";
@@ -14996,7 +14949,7 @@ function detectPlatform2() {
14996
14949
  const os = platform();
14997
14950
  if (os === "linux") {
14998
14951
  try {
14999
- const release = readFileSync45("/proc/version", "utf8").toLowerCase();
14952
+ const release = readFileSync44("/proc/version", "utf8").toLowerCase();
15000
14953
  if (release.includes("microsoft") || release.includes("wsl")) {
15001
14954
  return "wsl";
15002
14955
  }
@@ -15034,8 +14987,8 @@ async function compactCommand(options) {
15034
14987
  console.log(chalk54.dim("Install beads: https://github.com/steveyegge/beads"));
15035
14988
  process.exit(1);
15036
14989
  }
15037
- const beadsDir = join49(cwd, ".beads");
15038
- if (!existsSync50(beadsDir)) {
14990
+ const beadsDir = join48(cwd, ".beads");
14991
+ if (!existsSync49(beadsDir)) {
15039
14992
  console.error(chalk54.red("Error: No .beads directory found in current directory"));
15040
14993
  console.log(chalk54.dim("Run bd init to initialize beads"));
15041
14994
  process.exit(1);
@@ -15094,8 +15047,8 @@ async function statsCommand() {
15094
15047
  console.error(chalk54.red("Error: bd (beads) CLI not found"));
15095
15048
  process.exit(1);
15096
15049
  }
15097
- const beadsDir = join49(cwd, ".beads");
15098
- if (!existsSync50(beadsDir)) {
15050
+ const beadsDir = join48(cwd, ".beads");
15051
+ if (!existsSync49(beadsDir)) {
15099
15052
  console.error(chalk54.red("Error: No .beads directory found"));
15100
15053
  process.exit(1);
15101
15054
  }
@@ -15739,9 +15692,9 @@ import chalk60 from "chalk";
15739
15692
 
15740
15693
  // src/lib/env-loader.ts
15741
15694
  init_esm_shims();
15742
- import { join as join50 } from "path";
15743
- import { homedir as homedir23 } from "os";
15744
- var ENV_FILE_PATH = join50(homedir23(), ".panopticon.env");
15695
+ import { join as join49 } from "path";
15696
+ import { homedir as homedir22 } from "os";
15697
+ var ENV_FILE_PATH = join49(homedir22(), ".panopticon.env");
15745
15698
  function getShadowModeFromEnv() {
15746
15699
  const value = process.env.SHADOW_MODE;
15747
15700
  if (!value) return false;
@@ -15844,9 +15797,9 @@ import chalk61 from "chalk";
15844
15797
  // src/lib/costs/sync-wal.ts
15845
15798
  init_esm_shims();
15846
15799
  init_projects();
15847
- import { existsSync as existsSync51 } from "fs";
15800
+ import { existsSync as existsSync50 } from "fs";
15848
15801
  import { readdir, readFile } from "fs/promises";
15849
- import { join as join51 } from "path";
15802
+ import { join as join50 } from "path";
15850
15803
 
15851
15804
  // src/lib/database/cost-events-db.ts
15852
15805
  init_esm_shims();
@@ -15911,8 +15864,8 @@ async function syncWalFromAllProjects() {
15911
15864
  for (const { key, config: config2 } of projects) {
15912
15865
  const repoPath = config2.events_repo ?? config2.path;
15913
15866
  const eventsSubdir = config2.events_path ?? DEFAULT_EVENTS_SUBDIR;
15914
- const eventsDir = join51(repoPath, eventsSubdir);
15915
- if (!existsSync51(eventsDir)) continue;
15867
+ const eventsDir = join50(repoPath, eventsSubdir);
15868
+ if (!existsSync50(eventsDir)) continue;
15916
15869
  const projectStats = { imported: 0, duplicates: 0, files: 0 };
15917
15870
  let files;
15918
15871
  try {
@@ -15922,7 +15875,7 @@ async function syncWalFromAllProjects() {
15922
15875
  continue;
15923
15876
  }
15924
15877
  for (const file of files) {
15925
- const filePath = join51(eventsDir, file);
15878
+ const filePath = join50(eventsDir, file);
15926
15879
  const events = await parseWalFile(filePath, result.errors);
15927
15880
  if (events.length === 0) continue;
15928
15881
  try {
@@ -16249,10 +16202,10 @@ function createCostCommand() {
16249
16202
  }
16250
16203
 
16251
16204
  // src/cli/index.ts
16252
- var PANOPTICON_ENV_FILE = join52(homedir24(), ".panopticon.env");
16253
- if (existsSync52(PANOPTICON_ENV_FILE)) {
16205
+ var PANOPTICON_ENV_FILE = join51(homedir23(), ".panopticon.env");
16206
+ if (existsSync51(PANOPTICON_ENV_FILE)) {
16254
16207
  try {
16255
- const envContent = readFileSync46(PANOPTICON_ENV_FILE, "utf-8");
16208
+ const envContent = readFileSync45(PANOPTICON_ENV_FILE, "utf-8");
16256
16209
  for (const line of envContent.split("\n")) {
16257
16210
  const trimmed = line.trim();
16258
16211
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -16269,7 +16222,7 @@ if (existsSync52(PANOPTICON_ENV_FILE)) {
16269
16222
  }
16270
16223
  }
16271
16224
  var program = new Command2();
16272
- program.name("pan").description("Multi-agent orchestration for AI coding assistants").version(JSON.parse(readFileSync46(join52(import.meta.dirname, "../../package.json"), "utf-8")).version);
16225
+ program.name("pan").description("Multi-agent orchestration for AI coding assistants").version(JSON.parse(readFileSync45(join51(import.meta.dirname, "../../package.json"), "utf-8")).version);
16273
16226
  program.command("init").description("Initialize Panopticon (~/.panopticon/)").action(initCommand);
16274
16227
  program.command("sync").description("Sync skills/agents/rules to devroot").option("--dry-run", "Show what would be synced").option("--force", "Overwrite files modified since Panopticon installed them").option("--diff", "Show diff for modified files").option("--backup-only", "Only create backup").action(syncCommand);
16275
16228
  program.command("restore [timestamp]").description("Restore from backup").action(restoreCommand);
@@ -16293,21 +16246,21 @@ program.command("migrate-config").description("Migrate from settings.json to con
16293
16246
  program.command("status").description("Show running agents (shorthand for work status)").option("--json", "Output as JSON").option("--tldr", "Show TLDR index health across all workspaces").option("--context", "Show context window usage % for each agent").action(statusCommand);
16294
16247
  program.command("up").description("Start dashboard (and Traefik if enabled)").option("--detach", "Run in background").option("--skip-traefik", "Skip Traefik startup").action(async (options) => {
16295
16248
  const { spawn: spawn2, execSync: execSync9 } = await import("child_process");
16296
- const { join: join53, dirname: dirname16 } = await import("path");
16249
+ const { join: join52, dirname: dirname16 } = await import("path");
16297
16250
  const { fileURLToPath: fileURLToPath6 } = await import("url");
16298
- const { readFileSync: readFileSync47, existsSync: existsSync53 } = await import("fs");
16251
+ const { readFileSync: readFileSync46, existsSync: existsSync52 } = await import("fs");
16299
16252
  const { parse } = await import("@iarna/toml");
16300
16253
  const __dirname6 = dirname16(fileURLToPath6(import.meta.url));
16301
- const bundledServer = join53(__dirname6, "..", "dashboard", "server.js");
16302
- const srcDashboard = join53(__dirname6, "..", "..", "src", "dashboard");
16303
- const configFile = join53(process.env.HOME || "", ".panopticon", "config.toml");
16254
+ const bundledServer = join52(__dirname6, "..", "dashboard", "server.js");
16255
+ const srcDashboard = join52(__dirname6, "..", "..", "src", "dashboard");
16256
+ const configFile = join52(process.env.HOME || "", ".panopticon", "config.toml");
16304
16257
  let traefikEnabled = false;
16305
16258
  let traefikDomain = "pan.localhost";
16306
16259
  let dashboardPort = 3010;
16307
16260
  let dashboardApiPort = 3011;
16308
- if (existsSync53(configFile)) {
16261
+ if (existsSync52(configFile)) {
16309
16262
  try {
16310
- const configContent = readFileSync47(configFile, "utf-8");
16263
+ const configContent = readFileSync46(configFile, "utf-8");
16311
16264
  const config2 = parse(configContent);
16312
16265
  traefikEnabled = config2.traefik?.enabled === true;
16313
16266
  traefikDomain = config2.traefik?.domain || "pan.localhost";
@@ -16337,7 +16290,7 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
16337
16290
  }
16338
16291
  try {
16339
16292
  const { ensureBaseDomain: ensureBaseDomain2, detectDnsSyncMethod: detectDnsSyncMethod2, syncDnsToWindows: syncDnsToWindows2 } = await import("../dns-7BDJSD3E.js");
16340
- const dnsMethod = (existsSync53(configFile) ? parse(readFileSync47(configFile, "utf-8")).traefik?.dns_sync_method : null) || detectDnsSyncMethod2();
16293
+ const dnsMethod = (existsSync52(configFile) ? parse(readFileSync46(configFile, "utf-8")).traefik?.dns_sync_method : null) || detectDnsSyncMethod2();
16341
16294
  ensureBaseDomain2(dnsMethod, traefikDomain);
16342
16295
  if (dnsMethod === "wsl2hosts") {
16343
16296
  syncDnsToWindows2().catch(() => {
@@ -16360,19 +16313,19 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
16360
16313
  }
16361
16314
  }
16362
16315
  if (traefikEnabled && !options.skipTraefik) {
16363
- const traefikDir = join53(process.env.HOME || "", ".panopticon", "traefik");
16364
- if (existsSync53(traefikDir)) {
16316
+ const traefikDir = join52(process.env.HOME || "", ".panopticon", "traefik");
16317
+ if (existsSync52(traefikDir)) {
16365
16318
  try {
16366
- const composeFile = join53(traefikDir, "docker-compose.yml");
16367
- if (existsSync53(composeFile)) {
16368
- const content = readFileSync47(composeFile, "utf-8");
16319
+ const composeFile = join52(traefikDir, "docker-compose.yml");
16320
+ if (existsSync52(composeFile)) {
16321
+ const content = readFileSync46(composeFile, "utf-8");
16369
16322
  if (!content.includes("external: true") && content.includes("panopticon:")) {
16370
16323
  const patched = content.replace(
16371
16324
  /networks:\s*\n\s*panopticon:\s*\n\s*name: panopticon\s*\n\s*driver: bridge/,
16372
16325
  "networks:\n panopticon:\n name: panopticon\n external: true # Network created by 'pan install'"
16373
16326
  );
16374
- const { writeFileSync: writeFileSync27 } = await import("fs");
16375
- writeFileSync27(composeFile, patched);
16327
+ const { writeFileSync: writeFileSync26 } = await import("fs");
16328
+ writeFileSync26(composeFile, patched);
16376
16329
  console.log(chalk62.dim(" (migrated network config)"));
16377
16330
  }
16378
16331
  }
@@ -16390,8 +16343,8 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
16390
16343
  }
16391
16344
  }
16392
16345
  }
16393
- const isProduction = existsSync53(bundledServer);
16394
- const isDevelopment = existsSync53(srcDashboard);
16346
+ const isProduction = existsSync52(bundledServer);
16347
+ const isDevelopment = existsSync52(srcDashboard);
16395
16348
  if (!isProduction && !isDevelopment) {
16396
16349
  console.error(chalk62.red("Error: Dashboard not found"));
16397
16350
  console.error(chalk62.dim("This may be a corrupted installation. Try reinstalling panopticon-cli."));
@@ -16466,8 +16419,8 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
16466
16419
  try {
16467
16420
  const { getTldrDaemonService: getTldrDaemonService2 } = await import("../tldr-daemon-T3THOUGT.js");
16468
16421
  const projectRoot = process.cwd();
16469
- const venvPath = join53(projectRoot, ".venv");
16470
- if (existsSync53(venvPath)) {
16422
+ const venvPath = join52(projectRoot, ".venv");
16423
+ if (existsSync52(venvPath)) {
16471
16424
  console.log(chalk62.dim("\nStarting TLDR daemon for project root..."));
16472
16425
  const tldrService = getTldrDaemonService2(projectRoot, venvPath);
16473
16426
  await tldrService.start(true);
@@ -16483,17 +16436,17 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
16483
16436
  });
16484
16437
  program.command("down").description("Stop dashboard (and Traefik if enabled)").option("--skip-traefik", "Skip Traefik shutdown").action(async (options) => {
16485
16438
  const { execSync: execSync9 } = await import("child_process");
16486
- const { join: join53 } = await import("path");
16487
- const { readFileSync: readFileSync47, existsSync: existsSync53 } = await import("fs");
16439
+ const { join: join52 } = await import("path");
16440
+ const { readFileSync: readFileSync46, existsSync: existsSync52 } = await import("fs");
16488
16441
  const { parse } = await import("@iarna/toml");
16489
16442
  console.log(chalk62.bold("Stopping Panopticon...\n"));
16490
- const configFile = join53(process.env.HOME || "", ".panopticon", "config.toml");
16443
+ const configFile = join52(process.env.HOME || "", ".panopticon", "config.toml");
16491
16444
  let traefikEnabled = false;
16492
16445
  let dashboardPort = 3010;
16493
16446
  let dashboardApiPort = 3011;
16494
- if (existsSync53(configFile)) {
16447
+ if (existsSync52(configFile)) {
16495
16448
  try {
16496
- const configContent = readFileSync47(configFile, "utf-8");
16449
+ const configContent = readFileSync46(configFile, "utf-8");
16497
16450
  const config2 = parse(configContent);
16498
16451
  traefikEnabled = config2.traefik?.enabled === true;
16499
16452
  dashboardPort = config2.dashboard?.port || 3010;
@@ -16510,8 +16463,8 @@ program.command("down").description("Stop dashboard (and Traefik if enabled)").o
16510
16463
  console.log(chalk62.dim(" No dashboard processes found"));
16511
16464
  }
16512
16465
  if (traefikEnabled && !options.skipTraefik) {
16513
- const traefikDir = join53(process.env.HOME || "", ".panopticon", "traefik");
16514
- if (existsSync53(traefikDir)) {
16466
+ const traefikDir = join52(process.env.HOME || "", ".panopticon", "traefik");
16467
+ if (existsSync52(traefikDir)) {
16515
16468
  console.log(chalk62.dim("Stopping Traefik..."));
16516
16469
  try {
16517
16470
  execSync9("docker compose down", {
@@ -16530,8 +16483,8 @@ program.command("down").description("Stop dashboard (and Traefik if enabled)").o
16530
16483
  const { promisify: promisify21 } = await import("util");
16531
16484
  const execAsync21 = promisify21(exec21);
16532
16485
  const projectRoot = process.cwd();
16533
- const venvPath = join53(projectRoot, ".venv");
16534
- if (existsSync53(venvPath)) {
16486
+ const venvPath = join52(projectRoot, ".venv");
16487
+ if (existsSync52(venvPath)) {
16535
16488
  console.log(chalk62.dim("\nStopping TLDR daemon..."));
16536
16489
  const tldrService = getTldrDaemonService2(projectRoot, venvPath);
16537
16490
  await tldrService.stop();