@matthugh1/conductor-cli 0.2.2 → 0.2.4

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.
@@ -1,180 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- logGitActivity,
4
- removeWorktree
5
- } from "./chunk-KB2DTST2.js";
6
- import "./chunk-3MJBQK2F.js";
7
- import {
8
- getProjectPathById
9
- } from "./chunk-6VMREHG4.js";
10
- import {
11
- runGit
12
- } from "./chunk-FAZ7FCZQ.js";
13
- import {
14
- query
15
- } from "./chunk-PANC6BTV.js";
16
- import "./chunk-4YEHSYVN.js";
17
-
18
- // ../../src/core/cli-tasks.ts
19
- function rowToCliTask(row) {
20
- return {
21
- id: row.id,
22
- projectId: row.project_id,
23
- taskType: row.task_type,
24
- payload: row.payload,
25
- status: row.status,
26
- result: row.result,
27
- createdAt: new Date(row.created_at).toISOString(),
28
- startedAt: row.started_at ? new Date(row.started_at).toISOString() : null,
29
- completedAt: row.completed_at ? new Date(row.completed_at).toISOString() : null
30
- };
31
- }
32
- var ALLOWED_TASK_TYPES = /* @__PURE__ */ new Set([
33
- "remove_worktree",
34
- "delete_branch"
35
- ]);
36
- async function createCliTask(projectId, taskType, payload) {
37
- if (!ALLOWED_TASK_TYPES.has(taskType)) {
38
- throw new Error(`Unknown task type: ${taskType}`);
39
- }
40
- const rows = await query(
41
- `INSERT INTO cli_tasks (project_id, task_type, payload)
42
- VALUES ($1, $2, $3)
43
- RETURNING *`,
44
- [projectId, taskType, JSON.stringify(payload)]
45
- );
46
- return rowToCliTask(rows[0]);
47
- }
48
- async function claimNextTask(projectId) {
49
- const rows = await query(
50
- `UPDATE cli_tasks
51
- SET status = 'running', started_at = now()
52
- WHERE id = (
53
- SELECT id FROM cli_tasks
54
- WHERE project_id = $1 AND status = 'pending'
55
- ORDER BY created_at ASC
56
- LIMIT 1
57
- FOR UPDATE SKIP LOCKED
58
- )
59
- RETURNING *`,
60
- [projectId]
61
- );
62
- return rows.length > 0 ? rowToCliTask(rows[0]) : null;
63
- }
64
- async function completeTask(taskId, result = {}) {
65
- await query(
66
- `UPDATE cli_tasks
67
- SET status = 'done', result = $2, completed_at = now()
68
- WHERE id = $1`,
69
- [taskId, JSON.stringify(result)]
70
- );
71
- }
72
- async function failTask(taskId, error) {
73
- await query(
74
- `UPDATE cli_tasks
75
- SET status = 'failed', result = $2, completed_at = now()
76
- WHERE id = $1`,
77
- [taskId, JSON.stringify({ error })]
78
- );
79
- }
80
- async function listCliTasks(projectId, options) {
81
- const limit = options?.limit ?? 50;
82
- if (options?.status) {
83
- const rows2 = await query(
84
- `SELECT * FROM cli_tasks
85
- WHERE project_id = $1 AND status = $2
86
- ORDER BY created_at DESC
87
- LIMIT $3`,
88
- [projectId, options.status, limit]
89
- );
90
- return rows2.map(rowToCliTask);
91
- }
92
- const rows = await query(
93
- `SELECT * FROM cli_tasks
94
- WHERE project_id = $1
95
- ORDER BY created_at DESC
96
- LIMIT $2`,
97
- [projectId, limit]
98
- );
99
- return rows.map(rowToCliTask);
100
- }
101
- async function failStaleTasks(projectId) {
102
- const rows = await query(
103
- `UPDATE cli_tasks
104
- SET status = 'failed',
105
- result = '{"error": "Task timed out \u2014 pending for more than 24 hours"}'::jsonb,
106
- completed_at = now()
107
- WHERE project_id = $1
108
- AND status = 'pending'
109
- AND created_at < now() - interval '24 hours'
110
- RETURNING id`,
111
- [projectId]
112
- );
113
- return rows.length;
114
- }
115
- async function executeTask(task) {
116
- const projectRoot = await getProjectPathById(task.projectId);
117
- if (!projectRoot) {
118
- const msg = "Project path not found in database.";
119
- await failTask(task.id, msg);
120
- return msg;
121
- }
122
- try {
123
- switch (task.taskType) {
124
- case "remove_worktree":
125
- return await handleRemoveWorktree(task, projectRoot);
126
- case "delete_branch":
127
- return await handleDeleteBranch(task, projectRoot);
128
- default: {
129
- const msg = `Unknown task type: ${task.taskType}`;
130
- await failTask(task.id, msg);
131
- return msg;
132
- }
133
- }
134
- } catch (err) {
135
- const msg = err instanceof Error ? err.message : String(err);
136
- await failTask(task.id, msg);
137
- return `Failed: ${msg}`;
138
- }
139
- }
140
- async function handleRemoveWorktree(task, projectRoot) {
141
- const worktreeId = task.payload.worktreeId;
142
- if (!worktreeId) {
143
- const msg = "Missing worktreeId in task payload.";
144
- await failTask(task.id, msg);
145
- return msg;
146
- }
147
- await removeWorktree(task.projectId, projectRoot, worktreeId);
148
- await completeTask(task.id, { worktreeId });
149
- return `Removed worktree ${worktreeId}`;
150
- }
151
- async function handleDeleteBranch(task, projectRoot) {
152
- const branchName = task.payload.branchName;
153
- if (!branchName) {
154
- const msg = "Missing branchName in task payload.";
155
- await failTask(task.id, msg);
156
- return msg;
157
- }
158
- await runGit(projectRoot, ["branch", "-D", branchName]);
159
- await logGitActivity({
160
- projectId: task.projectId,
161
- initiativeId: null,
162
- worktreeId: null,
163
- eventType: "branch_delete",
164
- summary: `Deleted branch "${branchName}"`,
165
- plainEnglish: `Deleted the branch "${branchName}" from the local repository.`,
166
- branch: branchName,
167
- source: "system"
168
- });
169
- await completeTask(task.id, { branchName });
170
- return `Deleted branch "${branchName}"`;
171
- }
172
- export {
173
- claimNextTask,
174
- completeTask,
175
- createCliTask,
176
- executeTask,
177
- failStaleTasks,
178
- failTask,
179
- listCliTasks
180
- };
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- closePool,
4
- getClient,
5
- getPool,
6
- isDbReachable,
7
- query
8
- } from "./chunk-PANC6BTV.js";
9
- import "./chunk-4YEHSYVN.js";
10
- export {
11
- closePool,
12
- getClient,
13
- getPool,
14
- isDbReachable,
15
- query
16
- };
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- query
4
- } from "./chunk-PANC6BTV.js";
5
- import "./chunk-4YEHSYVN.js";
6
-
7
- // ../../src/core/git-snapshots.ts
8
- async function saveGitStatusSnapshot(projectId, data) {
9
- await query(
10
- `INSERT INTO git_status_snapshots
11
- (project_id, branch, branch_line, status, recent_commits, hook_status, worktree_commits, checked_at)
12
- VALUES ($1, $2, $3, $4, $5, $6, $7, now())
13
- ON CONFLICT (project_id)
14
- DO UPDATE SET
15
- branch = $2, branch_line = $3, status = $4,
16
- recent_commits = $5, hook_status = $6, worktree_commits = $7,
17
- checked_at = now()`,
18
- [
19
- projectId,
20
- data.branch,
21
- data.branchLine,
22
- data.status,
23
- JSON.stringify(data.recentCommits),
24
- data.hookStatus ? JSON.stringify(data.hookStatus) : null,
25
- JSON.stringify(data.worktreeCommits)
26
- ]
27
- );
28
- }
29
- async function getGitStatusSnapshot(projectId) {
30
- const rows = await query(
31
- `SELECT branch, branch_line, status, recent_commits, hook_status,
32
- worktree_commits, checked_at::text AS checked_at
33
- FROM git_status_snapshots
34
- WHERE project_id = $1`,
35
- [projectId]
36
- );
37
- if (rows.length === 0) return null;
38
- const r = rows[0];
39
- return {
40
- branch: r.branch,
41
- branchLine: r.branch_line,
42
- status: r.status,
43
- recentCommits: r.recent_commits,
44
- hookStatus: r.hook_status,
45
- worktreeCommits: r.worktree_commits,
46
- checkedAt: r.checked_at
47
- };
48
- }
49
- async function saveBranchOverviewSnapshot(projectId, data) {
50
- await query(
51
- `INSERT INTO branch_overview_snapshots
52
- (project_id, default_branch, current_branch, hide_overview, branches, checked_at)
53
- VALUES ($1, $2, $3, $4, $5, now())
54
- ON CONFLICT (project_id)
55
- DO UPDATE SET
56
- default_branch = $2, current_branch = $3, hide_overview = $4,
57
- branches = $5, checked_at = now()`,
58
- [
59
- projectId,
60
- data.defaultBranch,
61
- data.currentBranch,
62
- data.hideOverview,
63
- JSON.stringify(data.branches)
64
- ]
65
- );
66
- }
67
- async function getBranchOverviewSnapshot(projectId) {
68
- const rows = await query(
69
- `SELECT default_branch, current_branch, hide_overview, branches,
70
- checked_at::text AS checked_at
71
- FROM branch_overview_snapshots
72
- WHERE project_id = $1`,
73
- [projectId]
74
- );
75
- if (rows.length === 0) return null;
76
- const r = rows[0];
77
- return {
78
- defaultBranch: r.default_branch,
79
- currentBranch: r.current_branch,
80
- hideOverview: r.hide_overview,
81
- branches: r.branches,
82
- checkedAt: r.checked_at
83
- };
84
- }
85
- export {
86
- getBranchOverviewSnapshot,
87
- getGitStatusSnapshot,
88
- saveBranchOverviewSnapshot,
89
- saveGitStatusSnapshot
90
- };
@@ -1,147 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- getProjectPathById
4
- } from "./chunk-6VMREHG4.js";
5
- import {
6
- runGit
7
- } from "./chunk-FAZ7FCZQ.js";
8
- import {
9
- isDbReachable,
10
- query
11
- } from "./chunk-PANC6BTV.js";
12
- import "./chunk-4YEHSYVN.js";
13
-
14
- // ../../src/core/health.ts
15
- import { existsSync } from "fs";
16
- import path from "path";
17
- var processStartedAt = /* @__PURE__ */ new Date();
18
- function getDatabaseHost() {
19
- const raw = process.env.DATABASE_URL;
20
- if (!raw) return "localhost";
21
- try {
22
- const parsed = new URL(raw);
23
- return parsed.hostname;
24
- } catch {
25
- return "unknown";
26
- }
27
- }
28
- async function getHealthReport(transport) {
29
- const host = getDatabaseHost();
30
- const connected = await isDbReachable();
31
- let projectCount = 0;
32
- if (connected) {
33
- try {
34
- const rows = await query(
35
- "SELECT count(*)::text AS count FROM projects"
36
- );
37
- projectCount = rows.length > 0 ? parseInt(rows[0].count, 10) : 0;
38
- } catch {
39
- }
40
- }
41
- const now = /* @__PURE__ */ new Date();
42
- const uptimeSeconds = Math.floor(
43
- (now.getTime() - processStartedAt.getTime()) / 1e3
44
- );
45
- const status = connected ? "healthy" : "unhealthy";
46
- return {
47
- status,
48
- database: {
49
- host,
50
- connected,
51
- projectCount
52
- },
53
- server: {
54
- startedAt: processStartedAt.toISOString(),
55
- uptimeSeconds,
56
- transport
57
- }
58
- };
59
- }
60
- var CONDUCTOR_HOOK_MARKER = "# Conductor narration hook";
61
- async function runProbe(name, fn) {
62
- const start = performance.now();
63
- try {
64
- const result = await fn();
65
- return { name, ...result, durationMs: Math.round(performance.now() - start) };
66
- } catch (err) {
67
- const message = err instanceof Error ? err.message : "Unknown error";
68
- return {
69
- name,
70
- status: "fail",
71
- message,
72
- durationMs: Math.round(performance.now() - start)
73
- };
74
- }
75
- }
76
- async function getEnvironmentHealthReport(projectId) {
77
- const reportStart = performance.now();
78
- const [dbCheck, projectRoot] = await Promise.all([
79
- runProbe("Database", async () => {
80
- await query("SELECT 1");
81
- return { status: "pass", message: "Supabase connected" };
82
- }),
83
- getProjectPathById(projectId).catch(() => null)
84
- ]);
85
- const projectCheck = await runProbe("Project", async () => {
86
- if (projectRoot) {
87
- return { status: "pass", message: "Project registered" };
88
- }
89
- return {
90
- status: "fail",
91
- message: "Project not found in database",
92
- fixAction: { label: "Register project", href: "/settings" }
93
- };
94
- });
95
- let gitCheck;
96
- let hookCheck;
97
- if (projectRoot) {
98
- [gitCheck, hookCheck] = await Promise.all([
99
- runProbe("Git", async () => {
100
- const output = await runGit(projectRoot, ["--version"]);
101
- const version = output.trim().replace("git version ", "");
102
- return { status: "pass", message: `Git ${version} found` };
103
- }),
104
- runProbe("Hooks", async () => {
105
- const hookPath = path.join(projectRoot, ".git", "hooks", "post-commit");
106
- if (!existsSync(hookPath)) {
107
- return {
108
- status: "warn",
109
- message: "Hooks not installed",
110
- fixAction: { label: "Install hooks", href: "/git" }
111
- };
112
- }
113
- const { readFile } = await import("fs/promises");
114
- const content = await readFile(hookPath, "utf-8");
115
- if (!content.includes(CONDUCTOR_HOOK_MARKER)) {
116
- return {
117
- status: "warn",
118
- message: "Hook file exists but is not a Conductor hook",
119
- fixAction: { label: "Install hooks", href: "/git" }
120
- };
121
- }
122
- return { status: "pass", message: "Hooks installed" };
123
- })
124
- ]);
125
- } else {
126
- gitCheck = { name: "Git", status: "warn", message: "Skipped \u2014 no project path", durationMs: 0 };
127
- hookCheck = { name: "Hooks", status: "warn", message: "Skipped \u2014 no project path", durationMs: 0 };
128
- }
129
- const checks = [dbCheck, projectCheck, gitCheck, hookCheck];
130
- checks.sort((a, b) => {
131
- const order = { fail: 0, warn: 1, pass: 2 };
132
- return order[a.status] - order[b.status];
133
- });
134
- const hasFail = checks.some((c) => c.status === "fail");
135
- const hasWarn = checks.some((c) => c.status === "warn");
136
- const overall = hasFail ? "unhealthy" : hasWarn ? "degraded" : "healthy";
137
- return {
138
- checks,
139
- overall,
140
- checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
141
- totalDurationMs: Math.round(performance.now() - reportStart)
142
- };
143
- }
144
- export {
145
- getEnvironmentHealthReport,
146
- getHealthReport
147
- };
@@ -1,39 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- query
4
- } from "./chunk-PANC6BTV.js";
5
- import "./chunk-4YEHSYVN.js";
6
-
7
- // ../../src/core/health-snapshots.ts
8
- async function saveHealthSnapshot(projectId, report) {
9
- await query(
10
- `INSERT INTO health_snapshots (project_id, checks, overall, checked_at)
11
- VALUES ($1, $2, $3, $4)
12
- ON CONFLICT (project_id)
13
- DO UPDATE SET checks = $2, overall = $3, checked_at = $4`,
14
- [
15
- projectId,
16
- JSON.stringify(report.checks),
17
- report.overall,
18
- report.checkedAt
19
- ]
20
- );
21
- }
22
- async function getHealthSnapshot(projectId) {
23
- const rows = await query(
24
- `SELECT checks, overall, checked_at FROM health_snapshots WHERE project_id = $1`,
25
- [projectId]
26
- );
27
- if (rows.length === 0) return null;
28
- const row = rows[0];
29
- return {
30
- checks: row.checks,
31
- overall: row.overall,
32
- checkedAt: row.checked_at,
33
- totalDurationMs: 0
34
- };
35
- }
36
- export {
37
- getHealthSnapshot,
38
- saveHealthSnapshot
39
- };