taskplane 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -20
  3. package/bin/taskplane.mjs +706 -0
  4. package/dashboard/public/app.js +900 -0
  5. package/dashboard/public/index.html +92 -0
  6. package/dashboard/public/style.css +924 -0
  7. package/dashboard/server.cjs +531 -0
  8. package/extensions/task-orchestrator.ts +28 -0
  9. package/extensions/task-runner.ts +1923 -0
  10. package/extensions/taskplane/abort.ts +466 -0
  11. package/extensions/taskplane/config.ts +102 -0
  12. package/extensions/taskplane/discovery.ts +988 -0
  13. package/extensions/taskplane/engine.ts +758 -0
  14. package/extensions/taskplane/execution.ts +1752 -0
  15. package/extensions/taskplane/extension.ts +577 -0
  16. package/extensions/taskplane/formatting.ts +718 -0
  17. package/extensions/taskplane/git.ts +38 -0
  18. package/extensions/taskplane/index.ts +22 -0
  19. package/extensions/taskplane/merge.ts +795 -0
  20. package/extensions/taskplane/messages.ts +134 -0
  21. package/extensions/taskplane/persistence.ts +1121 -0
  22. package/extensions/taskplane/resume.ts +1092 -0
  23. package/extensions/taskplane/sessions.ts +92 -0
  24. package/extensions/taskplane/types.ts +1514 -0
  25. package/extensions/taskplane/waves.ts +900 -0
  26. package/extensions/taskplane/worktree.ts +1624 -0
  27. package/package.json +48 -3
  28. package/skills/create-taskplane-task/SKILL.md +326 -0
  29. package/skills/create-taskplane-task/references/context-template.md +78 -0
  30. package/skills/create-taskplane-task/references/prompt-template.md +246 -0
  31. package/templates/agents/task-merger.md +256 -0
  32. package/templates/agents/task-reviewer.md +81 -0
  33. package/templates/agents/task-worker.md +140 -0
  34. package/templates/config/task-orchestrator.yaml +89 -0
  35. package/templates/config/task-runner.yaml +99 -0
  36. package/templates/tasks/CONTEXT.md +31 -0
  37. package/templates/tasks/EXAMPLE-001-hello-world/PROMPT.md +90 -0
  38. package/templates/tasks/EXAMPLE-001-hello-world/STATUS.md +73 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * TMUX session discovery and formatting
3
+ * @module orch/sessions
4
+ */
5
+ import { execSync } from "child_process";
6
+ import { join } from "path";
7
+
8
+ import { tmuxHasSession } from "./execution.ts";
9
+ import { ORCH_MESSAGES } from "./messages.ts";
10
+ import type { OrchBatchRuntimeState, OrchestratorSessionEntry } from "./types.ts";
11
+
12
+ // ── Session Discovery ────────────────────────────────────────────────
13
+
14
+ /**
15
+ * List all TMUX sessions matching the orchestrator prefix.
16
+ *
17
+ * Parses `tmux list-sessions` output and filters by prefix.
18
+ * Returns entries sorted alphabetically by session name.
19
+ *
20
+ * @param tmuxPrefix - Prefix to match (e.g., "orch")
21
+ * @param batchState - Current batch state for enrichment (optional)
22
+ * @returns Array of session entries
23
+ */
24
+ export function listOrchSessions(
25
+ tmuxPrefix: string,
26
+ batchState?: OrchBatchRuntimeState,
27
+ ): OrchestratorSessionEntry[] {
28
+ let stdout = "";
29
+ try {
30
+ stdout = execSync('tmux list-sessions -F "#{session_name}"', {
31
+ encoding: "utf-8",
32
+ timeout: 5000,
33
+ });
34
+ } catch {
35
+ // No tmux server running or no sessions
36
+ return [];
37
+ }
38
+
39
+ const sessionNames = stdout
40
+ .trim()
41
+ .split("\n")
42
+ .filter(Boolean)
43
+ .filter(name => name.startsWith(`${tmuxPrefix}-`))
44
+ .sort();
45
+
46
+ if (sessionNames.length === 0) return [];
47
+
48
+ // Build a lookup from current batch state for enrichment
49
+ const laneLookup = new Map<string, { laneId: string; taskId: string | null; worktreePath: string }>();
50
+ if (batchState && batchState.currentLanes.length > 0) {
51
+ for (const lane of batchState.currentLanes) {
52
+ laneLookup.set(lane.tmuxSessionName, {
53
+ laneId: lane.laneId,
54
+ taskId: lane.tasks.length > 0 ? lane.tasks[0].taskId : null,
55
+ worktreePath: lane.worktreePath,
56
+ });
57
+ }
58
+ }
59
+
60
+ return sessionNames.map(name => {
61
+ const laneInfo = laneLookup.get(name);
62
+ return {
63
+ sessionName: name,
64
+ laneId: laneInfo?.laneId || "unknown",
65
+ taskId: laneInfo?.taskId || null,
66
+ status: tmuxHasSession(name) ? "alive" as const : "dead" as const,
67
+ worktreePath: laneInfo?.worktreePath || "",
68
+ attachCmd: `tmux attach -t ${name}`,
69
+ };
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Format session listing for display.
75
+ */
76
+ export function formatOrchSessions(sessions: OrchestratorSessionEntry[]): string {
77
+ if (sessions.length === 0) {
78
+ return ORCH_MESSAGES.sessionsNone();
79
+ }
80
+
81
+ const lines: string[] = [ORCH_MESSAGES.sessionsHeader(sessions.length), ""];
82
+
83
+ for (const s of sessions) {
84
+ const statusIcon = s.status === "alive" ? "🟢" : "🔴";
85
+ const taskInfo = s.taskId ? ` (${s.taskId})` : "";
86
+ lines.push(` ${statusIcon} ${s.sessionName} [${s.laneId}]${taskInfo}`);
87
+ lines.push(` ${s.attachCmd}`);
88
+ }
89
+
90
+ return lines.join("\n");
91
+ }
92
+