opencode-conductor-cdd-plugin 1.0.0-beta.17 → 1.0.0-beta.18
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/prompts/agent/cdd.md +16 -16
- package/dist/prompts/agent/implementer.md +5 -5
- package/dist/prompts/agent.md +7 -7
- package/dist/prompts/cdd/implement.json +1 -1
- package/dist/prompts/cdd/revert.json +1 -1
- package/dist/prompts/cdd/setup.json +1 -1
- package/dist/test/integration/rebrand.test.js +15 -14
- package/dist/utils/agentMapping.js +2 -0
- package/dist/utils/archive-tracks.d.ts +28 -0
- package/dist/utils/archive-tracks.js +154 -1
- package/dist/utils/archive-tracks.test.d.ts +1 -0
- package/dist/utils/archive-tracks.test.js +495 -0
- package/dist/utils/metadataTracker.d.ts +39 -0
- package/dist/utils/metadataTracker.js +105 -0
- package/dist/utils/metadataTracker.test.d.ts +1 -0
- package/dist/utils/metadataTracker.test.js +265 -0
- package/dist/utils/planParser.d.ts +25 -0
- package/dist/utils/planParser.js +107 -0
- package/dist/utils/planParser.test.d.ts +1 -0
- package/dist/utils/planParser.test.js +119 -0
- package/dist/utils/statusDisplay.d.ts +35 -0
- package/dist/utils/statusDisplay.js +81 -0
- package/dist/utils/statusDisplay.test.d.ts +1 -0
- package/dist/utils/statusDisplay.test.js +102 -0
- package/package.json +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// ANSI color codes
|
|
2
|
+
const colors = {
|
|
3
|
+
reset: "\x1b[0m",
|
|
4
|
+
bright: "\x1b[1m",
|
|
5
|
+
dim: "\x1b[2m",
|
|
6
|
+
green: "\x1b[32m",
|
|
7
|
+
yellow: "\x1b[33m",
|
|
8
|
+
blue: "\x1b[34m",
|
|
9
|
+
cyan: "\x1b[36m",
|
|
10
|
+
gray: "\x1b[90m"
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Calculates progress percentage
|
|
14
|
+
* @param completed Number of completed items
|
|
15
|
+
* @param total Total number of items
|
|
16
|
+
* @returns Progress percentage (0-100)
|
|
17
|
+
*/
|
|
18
|
+
export function calculateProgress(completed, total) {
|
|
19
|
+
if (total === 0)
|
|
20
|
+
return 0;
|
|
21
|
+
return Math.round((completed / total) * 100);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Generates a visual progress bar
|
|
25
|
+
* @param percentage Progress percentage (0-100)
|
|
26
|
+
* @param length Length of the progress bar (default: 20)
|
|
27
|
+
* @returns Progress bar string
|
|
28
|
+
*/
|
|
29
|
+
export function generateProgressBar(percentage, length = 20) {
|
|
30
|
+
const filled = Math.round((percentage / 100) * length);
|
|
31
|
+
const empty = length - filled;
|
|
32
|
+
return "█".repeat(filled) + "░".repeat(empty);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Formats track status into a visually appealing display
|
|
36
|
+
* @param track Track status information
|
|
37
|
+
* @param options Formatting options
|
|
38
|
+
* @returns Formatted status string
|
|
39
|
+
*/
|
|
40
|
+
export function formatTrackStatus(track, options = {}) {
|
|
41
|
+
const { compact = false, noColor = false, barLength = 20 } = options;
|
|
42
|
+
const c = noColor
|
|
43
|
+
? {
|
|
44
|
+
reset: "",
|
|
45
|
+
bright: "",
|
|
46
|
+
dim: "",
|
|
47
|
+
green: "",
|
|
48
|
+
yellow: "",
|
|
49
|
+
blue: "",
|
|
50
|
+
cyan: "",
|
|
51
|
+
gray: ""
|
|
52
|
+
}
|
|
53
|
+
: colors;
|
|
54
|
+
const progress = calculateProgress(track.completedTasks, track.totalTasks);
|
|
55
|
+
const progressBar = generateProgressBar(progress, barLength);
|
|
56
|
+
if (compact) {
|
|
57
|
+
return `${c.bright}${track.trackName}${c.reset} ${c.gray}[${track.trackId}]${c.reset}
|
|
58
|
+
${c.cyan}${track.currentPhase}${c.reset} ${c.dim}|${c.reset} ${c.green}${track.completedTasks}${c.reset}/${track.totalTasks} tasks ${c.dim}(${progress}%)${c.reset}`;
|
|
59
|
+
}
|
|
60
|
+
const inProgressInfo = track.inProgressTasks > 0 ? `, ${track.inProgressTasks} in progress` : "";
|
|
61
|
+
const formattedDate = new Date(track.lastUpdated).toLocaleString("en-US", {
|
|
62
|
+
year: "numeric",
|
|
63
|
+
month: "short",
|
|
64
|
+
day: "numeric",
|
|
65
|
+
hour: "2-digit",
|
|
66
|
+
minute: "2-digit"
|
|
67
|
+
});
|
|
68
|
+
return `${c.bright}${c.blue}━━━ Track Status ━━━${c.reset}
|
|
69
|
+
|
|
70
|
+
${c.bright}Track:${c.reset} ${track.trackName}
|
|
71
|
+
${c.dim}ID: ${track.trackId}${c.reset}
|
|
72
|
+
|
|
73
|
+
${c.bright}Phase:${c.reset} ${c.cyan}${track.currentPhase}${c.reset}
|
|
74
|
+
|
|
75
|
+
${c.bright}Progress:${c.reset} ${c.green}${track.completedTasks}${c.reset}/${track.totalTasks} tasks ${c.dim}(${progress}%)${c.reset}${inProgressInfo}
|
|
76
|
+
${progressBar}
|
|
77
|
+
|
|
78
|
+
${c.gray}Last updated: ${formattedDate}${c.reset}
|
|
79
|
+
|
|
80
|
+
${c.bright}${c.blue}━━━━━━━━━━━━━━━━━━━━${c.reset}`;
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { formatTrackStatus, calculateProgress, generateProgressBar } from "./statusDisplay.js";
|
|
3
|
+
describe("statusDisplay", () => {
|
|
4
|
+
describe("calculateProgress", () => {
|
|
5
|
+
it("should calculate progress percentage correctly", () => {
|
|
6
|
+
expect(calculateProgress(3, 10)).toBe(30);
|
|
7
|
+
expect(calculateProgress(5, 5)).toBe(100);
|
|
8
|
+
expect(calculateProgress(0, 10)).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
it("should handle zero total gracefully", () => {
|
|
11
|
+
expect(calculateProgress(0, 0)).toBe(0);
|
|
12
|
+
});
|
|
13
|
+
it("should round to nearest integer", () => {
|
|
14
|
+
expect(calculateProgress(1, 3)).toBe(33);
|
|
15
|
+
expect(calculateProgress(2, 3)).toBe(67);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe("generateProgressBar", () => {
|
|
19
|
+
it("should generate a progress bar with default length", () => {
|
|
20
|
+
const bar = generateProgressBar(50);
|
|
21
|
+
expect(bar).toHaveLength(20); // Default bar length
|
|
22
|
+
expect(bar).toContain("█");
|
|
23
|
+
expect(bar).toContain("░");
|
|
24
|
+
});
|
|
25
|
+
it("should generate full bar at 100%", () => {
|
|
26
|
+
const bar = generateProgressBar(100, 10);
|
|
27
|
+
expect(bar).toBe("██████████");
|
|
28
|
+
});
|
|
29
|
+
it("should generate empty bar at 0%", () => {
|
|
30
|
+
const bar = generateProgressBar(0, 10);
|
|
31
|
+
expect(bar).toBe("░░░░░░░░░░");
|
|
32
|
+
});
|
|
33
|
+
it("should handle custom bar length", () => {
|
|
34
|
+
const bar = generateProgressBar(50, 30);
|
|
35
|
+
expect(bar).toHaveLength(30);
|
|
36
|
+
});
|
|
37
|
+
it("should show correct filled/unfilled ratio", () => {
|
|
38
|
+
const bar = generateProgressBar(25, 8);
|
|
39
|
+
expect(bar).toBe("██░░░░░░"); // 25% of 8 = 2 filled
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe("formatTrackStatus", () => {
|
|
43
|
+
const sampleTrack = {
|
|
44
|
+
trackId: "track_test_123",
|
|
45
|
+
trackName: "Implement Authentication",
|
|
46
|
+
totalTasks: 10,
|
|
47
|
+
completedTasks: 7,
|
|
48
|
+
inProgressTasks: 1,
|
|
49
|
+
currentPhase: "Phase 2: Implementation",
|
|
50
|
+
lastUpdated: "2026-01-18T12:00:00Z"
|
|
51
|
+
};
|
|
52
|
+
it("should format a complete track status display", () => {
|
|
53
|
+
const status = formatTrackStatus(sampleTrack);
|
|
54
|
+
expect(status).toContain("Implement Authentication");
|
|
55
|
+
expect(status).toContain("Phase 2: Implementation");
|
|
56
|
+
expect(status).toMatch(/7.*\/.*10.*tasks/); // Match "7/10 tasks" with potential ANSI codes
|
|
57
|
+
expect(status).toContain("█"); // Progress bar
|
|
58
|
+
expect(status).toContain("Last updated:");
|
|
59
|
+
});
|
|
60
|
+
it("should show 100% completion for fully complete track", () => {
|
|
61
|
+
const completeTrack = {
|
|
62
|
+
...sampleTrack,
|
|
63
|
+
completedTasks: 10,
|
|
64
|
+
inProgressTasks: 0,
|
|
65
|
+
currentPhase: "Completed"
|
|
66
|
+
};
|
|
67
|
+
const status = formatTrackStatus(completeTrack);
|
|
68
|
+
expect(status).toContain("100%");
|
|
69
|
+
expect(status).toMatch(/10.*\/.*10.*tasks/); // Match "10/10 tasks" with potential ANSI codes
|
|
70
|
+
});
|
|
71
|
+
it("should indicate in-progress tasks", () => {
|
|
72
|
+
const status = formatTrackStatus(sampleTrack);
|
|
73
|
+
expect(status).toContain("1 in progress");
|
|
74
|
+
});
|
|
75
|
+
it("should handle track with no tasks", () => {
|
|
76
|
+
const emptyTrack = {
|
|
77
|
+
...sampleTrack,
|
|
78
|
+
totalTasks: 0,
|
|
79
|
+
completedTasks: 0,
|
|
80
|
+
inProgressTasks: 0
|
|
81
|
+
};
|
|
82
|
+
const status = formatTrackStatus(emptyTrack);
|
|
83
|
+
expect(status).toMatch(/0.*\/.*0.*tasks/); // Match "0/0 tasks" with potential ANSI codes
|
|
84
|
+
expect(status).toContain("0%");
|
|
85
|
+
});
|
|
86
|
+
it("should include color indicators in status (ANSI codes)", () => {
|
|
87
|
+
const status = formatTrackStatus(sampleTrack);
|
|
88
|
+
// Should contain ANSI escape codes for colors
|
|
89
|
+
expect(status).toMatch(/\x1b\[\d+m/); // Contains ANSI color codes
|
|
90
|
+
});
|
|
91
|
+
it("should format status with compact mode option", () => {
|
|
92
|
+
const status = formatTrackStatus(sampleTrack, { compact: true });
|
|
93
|
+
// Compact mode should be shorter (no progress bar or timestamps)
|
|
94
|
+
expect(status.split("\n").length).toBeLessThan(5);
|
|
95
|
+
});
|
|
96
|
+
it("should allow disabling color output", () => {
|
|
97
|
+
const status = formatTrackStatus(sampleTrack, { noColor: true });
|
|
98
|
+
// Should not contain ANSI escape codes
|
|
99
|
+
expect(status).not.toMatch(/\x1b\[\d+m/);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-conductor-cdd-plugin",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.18",
|
|
4
4
|
"description": "Context-Driven Development (CDD) plugin for OpenCode - Transform your AI coding workflow with structured specifications, plans, and implementation tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|