zugzbot 1.0.27 → 1.0.29
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.
|
@@ -41,6 +41,7 @@ Eres el coordinador principal del arnés de desarrollo SDD (Spec-Driven Developm
|
|
|
41
41
|
- **Ruta de Capturas**: Guarda cualquier screenshot de Playwright en `.openspec/ts-<nombre>.png`.
|
|
42
42
|
- **Sistema de Memoria (Brain)**: Consulta el cerebro con `sdd_get_initial_session_data` al inicio (F0/F1) para entender el historial del proyecto. Guarda los aprendizajes clave al final en `<completion>` con `brain_save_memory`.
|
|
43
43
|
- **Modo Autopiloto (`/loop`)**: Si se detecta `loopMode: true` o comando `/loop`, autotomará el 100% de las decisiones recomendadas por defecto. Tienes PROHIBIDO usar la tool `question` en autopiloto.
|
|
44
|
+
- **Modo Libre / Fast-Track**: Si detectas que el estado es `F2_IMPLEMENTATION` y el contrato activo contiene `fast-track` (Modo Libre), reconócelo como el estado normal de Modo Libre/Fast-Track para consultas generales y ediciones libres de código. NO reportes esto como un estado inválido, roto o stale, ni te quejes de que falta el contrato. En su lugar, dale la bienvenida al usuario, explícale que tiene libertad total para programar o consultar, y ofrécele opcionalmente guiarle en un flujo estructurado de desarrollo formal (F0->F4) si lo desea.
|
|
44
45
|
</constraints>
|
|
45
46
|
|
|
46
47
|
<workflow>
|
|
@@ -12,20 +12,14 @@ const PluginTuiSidebar: TuiPlugin = async (api) => {
|
|
|
12
12
|
const [sessionIds, setSessionIds] = createSignal<string[]>([props.session_id])
|
|
13
13
|
|
|
14
14
|
const getZugzbotVersion = (): string => {
|
|
15
|
-
const fallback = "
|
|
15
|
+
const fallback = "2.0.18"
|
|
16
16
|
try {
|
|
17
|
-
// Try to read from our dynamic version metadata file
|
|
18
|
-
const localVersionPath = path.join(process.cwd(), ".opencode/version.json")
|
|
19
|
-
if (fs.existsSync(localVersionPath)) {
|
|
20
|
-
const versionData = JSON.parse(fs.readFileSync(localVersionPath, "utf-8"))
|
|
21
|
-
if (versionData && versionData.version) return versionData.version
|
|
22
|
-
}
|
|
23
17
|
const localPkgPath = path.join(process.cwd(), "package.json")
|
|
24
18
|
if (fs.existsSync(localPkgPath)) {
|
|
25
19
|
const pkg = JSON.parse(fs.readFileSync(localPkgPath, "utf-8"))
|
|
26
|
-
if (pkg.name === "zugzbot
|
|
20
|
+
if (pkg.name === "zugzbot-sdd") return pkg.version
|
|
27
21
|
}
|
|
28
|
-
const depPkgPath = path.join(process.cwd(), "node_modules/zugzbot/package.json")
|
|
22
|
+
const depPkgPath = path.join(process.cwd(), "node_modules/zugzbot-sdd/package.json")
|
|
29
23
|
if (fs.existsSync(depPkgPath)) {
|
|
30
24
|
const pkg = JSON.parse(fs.readFileSync(depPkgPath, "utf-8"))
|
|
31
25
|
return pkg.version || fallback
|
|
@@ -143,6 +137,7 @@ const PluginTuiSidebar: TuiPlugin = async (api) => {
|
|
|
143
137
|
|
|
144
138
|
const getContractName = (filePath: string): string => {
|
|
145
139
|
if (!filePath) return "Ninguno";
|
|
140
|
+
if (filePath.includes("fast-track")) return "Modo Libre (Fast-Track)";
|
|
146
141
|
const parts = filePath.split("/");
|
|
147
142
|
const folder = parts[parts.length - 2] || "";
|
|
148
143
|
const match = folder.match(/^\d{4}_\d+_(.+)$/);
|
|
@@ -559,35 +554,46 @@ const PluginTuiSidebar: TuiPlugin = async (api) => {
|
|
|
559
554
|
})()}
|
|
560
555
|
|
|
561
556
|
{/* Vertical roadmap list */}
|
|
562
|
-
|
|
563
|
-
{
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
557
|
+
{sddState()?.activeContract?.includes("fast-track") ? (
|
|
558
|
+
<box gap={0} paddingTop={0}>
|
|
559
|
+
<text fg="#5AC8FA" paddingTop={0}>
|
|
560
|
+
{"• Modo Libre de Edición"}
|
|
561
|
+
</text>
|
|
562
|
+
<text fg="#FF7300" paddingTop={0}>
|
|
563
|
+
{`• Agente activo: ${SUBAGENT_FOR_PHASE[sddState()?.phase || "F2_IMPLEMENTATION"] || "@coder"}`}
|
|
564
|
+
</text>
|
|
565
|
+
</box>
|
|
566
|
+
) : (
|
|
567
|
+
<box gap={0} paddingTop={0}>
|
|
568
|
+
{PHASE_ORDER.map((phase) => {
|
|
569
|
+
const current = sddState()?.phase ?? "F0_DETECT"
|
|
570
|
+
const curIdx = PHASE_ORDER.indexOf(current)
|
|
571
|
+
const myIdx = PHASE_ORDER.indexOf(phase)
|
|
572
|
+
|
|
573
|
+
const isActive = current === phase
|
|
574
|
+
const isCompleted = curIdx > myIdx
|
|
575
|
+
|
|
576
|
+
let prefix = "[ ]"
|
|
577
|
+
let color = api.theme.current.textMuted
|
|
578
|
+
if (isCompleted) {
|
|
579
|
+
prefix = "[✓]"
|
|
580
|
+
color = api.theme.current.success
|
|
581
|
+
} else if (isActive) {
|
|
582
|
+
prefix = "[O]"
|
|
583
|
+
color = "#FF7300"
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const agentSuffix = isActive ? ` (${SUBAGENT_FOR_PHASE[phase]})` : ""
|
|
587
|
+
const lineText = `${prefix} ${PHASE_LABELS[phase]}${agentSuffix}`
|
|
588
|
+
|
|
589
|
+
return (
|
|
590
|
+
<text fg={color} paddingTop={0}>
|
|
591
|
+
{truncate(lineText, 34)}
|
|
592
|
+
</text>
|
|
593
|
+
)
|
|
594
|
+
})}
|
|
595
|
+
</box>
|
|
596
|
+
)}
|
|
591
597
|
|
|
592
598
|
{/* Git branch info */}
|
|
593
599
|
{(sddState()?.git?.branch && sddState()?.git?.branch !== "—") ? (
|
|
@@ -191,6 +191,24 @@ export const SddBridgePlugin: Plugin = async ({ project, client, $, directory, w
|
|
|
191
191
|
writeMetrics(metrics)
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
// Ensure .openspec/active-brief.md exists physically on load to prevent OpenCode startup crash on raw workspaces
|
|
195
|
+
const activeBriefPath = path.resolve(projectRoot, ".openspec/active-brief.md")
|
|
196
|
+
if (!fs.existsSync(activeBriefPath)) {
|
|
197
|
+
try {
|
|
198
|
+
const openspecDir = path.dirname(activeBriefPath)
|
|
199
|
+
if (!fs.existsSync(openspecDir)) {
|
|
200
|
+
fs.mkdirSync(openspecDir, { recursive: true })
|
|
201
|
+
}
|
|
202
|
+
fs.writeFileSync(
|
|
203
|
+
activeBriefPath,
|
|
204
|
+
"# SDD Active Brief\n\nNo hay ninguna sesión activa o el spec actual no ha sido iniciado.\n",
|
|
205
|
+
"utf8"
|
|
206
|
+
)
|
|
207
|
+
} catch (e) {
|
|
208
|
+
// best-effort
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
194
212
|
// Helper to synchronize models automatically from models.json
|
|
195
213
|
const syncModelsFromConfig = () => {
|
|
196
214
|
try {
|
package/bin/init.js
CHANGED
|
@@ -19,23 +19,14 @@ const bold = '\x1b[1m';
|
|
|
19
19
|
const pkgRoot = join(__dirname, '..');
|
|
20
20
|
const targetDir = process.cwd();
|
|
21
21
|
|
|
22
|
-
// Read version from package.json dynamically
|
|
23
|
-
let version = '1.0.27';
|
|
24
|
-
try {
|
|
25
|
-
const pkg = JSON.parse(fs.readFileSync(join(pkgRoot, 'package.json'), 'utf8'));
|
|
26
|
-
version = pkg.version || version;
|
|
27
|
-
} catch (e) {
|
|
28
|
-
// fallback
|
|
29
|
-
}
|
|
30
|
-
|
|
31
22
|
const banner = `
|
|
32
23
|
${bold}${orange}███████╗██╗ ██╗ ██████╗ ███████╗
|
|
33
24
|
╚══███╔╝██║ ██║██╔════╝ ╚══███╔╝
|
|
34
25
|
███╔╝ ██║ ██║██║ ███╗ ███╔╝
|
|
35
|
-
|
|
26
|
+
███╔╝ ██║ ██║██║ ██║ ███╔╝
|
|
36
27
|
███████╗╚██████╔╝╚██████╔╝███████╗
|
|
37
28
|
╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝${reset}
|
|
38
|
-
${bold}${yellow} Harness Installer
|
|
29
|
+
${bold}${yellow} Harness Installer v1.0.7${reset}\n`;
|
|
39
30
|
|
|
40
31
|
console.log(banner);
|
|
41
32
|
console.log(`${bold}${cyan}🔍 Detectando entorno de trabajo...${reset}`);
|
|
@@ -97,15 +88,6 @@ for (const item of itemsToCopy) {
|
|
|
97
88
|
console.error(`${red}❌ Error copying ${item.name}: ${error.message}${reset}`);
|
|
98
89
|
}
|
|
99
90
|
}
|
|
100
|
-
|
|
101
|
-
// Write version metadata to target's .opencode/version.json
|
|
102
|
-
try {
|
|
103
|
-
const versionPath = join(targetDir, '.opencode', 'version.json');
|
|
104
|
-
fs.writeFileSync(versionPath, JSON.stringify({ version }, null, 2), 'utf8');
|
|
105
|
-
} catch (error) {
|
|
106
|
-
// silent best-effort
|
|
107
|
-
}
|
|
108
|
-
|
|
109
91
|
// Ensure .openspec/ is ignored in the target's .gitignore to avoid propagating local state
|
|
110
92
|
try {
|
|
111
93
|
const gitignorePath = join(targetDir, '.gitignore');
|