@lugom.io/hefesto 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.
- package/agents/.gitkeep +0 -0
- package/bin/install.js +410 -0
- package/commands/hefesto/init.md +45 -0
- package/commands/hefesto/new-feature.md +50 -0
- package/commands/hefesto/status.md +40 -0
- package/commands/hefesto/update.md +31 -0
- package/hooks/hefesto-check-update.cjs +60 -0
- package/hooks/hefesto-statusline.cjs +75 -0
- package/package.json +37 -0
- package/skills/hefesto-context/SKILL.md +66 -0
- package/templates/FEATURE.md +52 -0
- package/templates/PROJECT.md +28 -0
- package/templates/ROADMAP.md +23 -0
- package/templates/STATE.md +37 -0
package/agents/.gitkeep
ADDED
|
File without changes
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Hefesto Installer
|
|
4
|
+
// Instala o toolkit .hefesto/ + skills/commands no runtime do projeto.
|
|
5
|
+
// Claude Code first, com suporte a Gemini e Codex.
|
|
6
|
+
// Zero dependências externas.
|
|
7
|
+
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
16
|
+
|
|
17
|
+
// ── ANSI Colors ─────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
const red = '\x1b[31m';
|
|
20
|
+
const dim = '\x1b[2m';
|
|
21
|
+
const reset = '\x1b[0m';
|
|
22
|
+
|
|
23
|
+
const banner = '\n' +
|
|
24
|
+
red + ' ██╗ ██╗███████╗███████╗███████╗███████╗████████╗ ██████╗\n' +
|
|
25
|
+
' ██║ ██║██╔════╝██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔═══██╗\n' +
|
|
26
|
+
' ███████║█████╗ █████╗ █████╗ ███████╗ ██║ ██║ ██║\n' +
|
|
27
|
+
' ██╔══██║██╔══╝ ██╔══╝ ██╔══╝ ╚════██║ ██║ ██║ ██║\n' +
|
|
28
|
+
' ██║ ██║███████╗██║ ███████╗███████║ ██║ ╚██████╔╝\n' +
|
|
29
|
+
' ╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝╚══════╝ ╚═╝ ╚═════╝\n' + reset +
|
|
30
|
+
dim + ' Toolkit spec-driven + story-driven para agentes AI\n' + reset;
|
|
31
|
+
|
|
32
|
+
// ── CLI Args ────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
const args = process.argv.slice(2);
|
|
35
|
+
const hasGlobal = args.includes('--global') || args.includes('-g');
|
|
36
|
+
const hasUninstall = args.includes('--uninstall') || args.includes('-u');
|
|
37
|
+
const hasHelp = args.includes('--help') || args.includes('-h');
|
|
38
|
+
|
|
39
|
+
const hasClaude = args.includes('--claude');
|
|
40
|
+
const hasGemini = args.includes('--gemini');
|
|
41
|
+
const hasCodex = args.includes('--codex');
|
|
42
|
+
const hasAll = args.includes('--all');
|
|
43
|
+
|
|
44
|
+
// ── Help ────────────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
if (hasHelp) {
|
|
47
|
+
console.log(banner);
|
|
48
|
+
console.log(` Uso:
|
|
49
|
+
npx @lugom.io/hefesto [opções]
|
|
50
|
+
|
|
51
|
+
Opções:
|
|
52
|
+
--claude Instala para Claude Code (padrão)
|
|
53
|
+
--gemini Instala para Gemini CLI
|
|
54
|
+
--codex Instala para Codex
|
|
55
|
+
--all Instala para todos os runtimes
|
|
56
|
+
--global, -g Instalação global (~/.claude/, etc.)
|
|
57
|
+
--uninstall, -u Remove o Hefesto
|
|
58
|
+
--help, -h Mostra esta ajuda
|
|
59
|
+
|
|
60
|
+
Exemplos:
|
|
61
|
+
npx @lugom.io/hefesto # Instala para Claude Code (local)
|
|
62
|
+
npx @lugom.io/hefesto --global # Instala para Claude Code (global)
|
|
63
|
+
npx @lugom.io/hefesto --all # Instala para todos os runtimes
|
|
64
|
+
npx @lugom.io/hefesto --uninstall # Remove o Hefesto
|
|
65
|
+
`);
|
|
66
|
+
process.exit(0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── Runtime Detection ───────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
function getSelectedRuntimes() {
|
|
72
|
+
if (hasAll) return ['claude', 'gemini', 'codex'];
|
|
73
|
+
const runtimes = [];
|
|
74
|
+
if (hasClaude) runtimes.push('claude');
|
|
75
|
+
if (hasGemini) runtimes.push('gemini');
|
|
76
|
+
if (hasCodex) runtimes.push('codex');
|
|
77
|
+
// Default: Claude Code
|
|
78
|
+
if (runtimes.length === 0) runtimes.push('claude');
|
|
79
|
+
return runtimes;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── Path Resolution ─────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
function getRuntimeDirName(runtime) {
|
|
85
|
+
if (runtime === 'gemini') return '.gemini';
|
|
86
|
+
if (runtime === 'codex') return '.codex';
|
|
87
|
+
return '.claude';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function getGlobalDir(runtime) {
|
|
91
|
+
if (runtime === 'gemini') {
|
|
92
|
+
if (process.env.GEMINI_CONFIG_DIR) return path.resolve(process.env.GEMINI_CONFIG_DIR);
|
|
93
|
+
return path.join(os.homedir(), '.gemini');
|
|
94
|
+
}
|
|
95
|
+
if (runtime === 'codex') {
|
|
96
|
+
if (process.env.CODEX_HOME) return path.resolve(process.env.CODEX_HOME);
|
|
97
|
+
return path.join(os.homedir(), '.codex');
|
|
98
|
+
}
|
|
99
|
+
// Claude Code
|
|
100
|
+
if (process.env.CLAUDE_CONFIG_DIR) return path.resolve(process.env.CLAUDE_CONFIG_DIR);
|
|
101
|
+
return path.join(os.homedir(), '.claude');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getRuntimeDir(runtime) {
|
|
105
|
+
if (hasGlobal) return getGlobalDir(runtime);
|
|
106
|
+
return path.join(process.cwd(), getRuntimeDirName(runtime));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getHefestoDir() {
|
|
110
|
+
if (hasGlobal) return path.join(os.homedir(), '.hefesto');
|
|
111
|
+
return path.join(process.cwd(), '.hefesto');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ── File Operations ─────────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
function ensureDir(dirPath) {
|
|
117
|
+
if (!fs.existsSync(dirPath)) {
|
|
118
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function copyDir(src, dest) {
|
|
123
|
+
ensureDir(dest);
|
|
124
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
125
|
+
for (const entry of entries) {
|
|
126
|
+
const srcPath = path.join(src, entry.name);
|
|
127
|
+
const destPath = path.join(dest, entry.name);
|
|
128
|
+
if (entry.isDirectory()) {
|
|
129
|
+
copyDir(srcPath, destPath);
|
|
130
|
+
} else {
|
|
131
|
+
fs.copyFileSync(srcPath, destPath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function removeIfExists(targetPath) {
|
|
137
|
+
if (fs.existsSync(targetPath)) {
|
|
138
|
+
fs.rmSync(targetPath, { recursive: true });
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ── Default Config ──────────────────────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
function createDefaultConfig() {
|
|
147
|
+
return {
|
|
148
|
+
version: '0.1.0',
|
|
149
|
+
project: { name: '', language: 'pt-BR' },
|
|
150
|
+
runtime: 'claude',
|
|
151
|
+
feature: { id_prefix: 'FEAT', counter: 0 },
|
|
152
|
+
lifecycle: { auto_update_state: true },
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ── Install ─────────────────────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
function installHefesto() {
|
|
159
|
+
const hefestoDir = getHefestoDir();
|
|
160
|
+
const templatesDir = path.join(PKG_ROOT, 'templates');
|
|
161
|
+
|
|
162
|
+
console.log(banner);
|
|
163
|
+
console.log(` Instalando...\n`);
|
|
164
|
+
|
|
165
|
+
// 1. Criar .hefesto/ com scaffold
|
|
166
|
+
if (fs.existsSync(hefestoDir)) {
|
|
167
|
+
console.log(` ℹ️ .hefesto/ já existe, mantendo estado do projeto.`);
|
|
168
|
+
} else {
|
|
169
|
+
ensureDir(hefestoDir);
|
|
170
|
+
ensureDir(path.join(hefestoDir, 'features'));
|
|
171
|
+
|
|
172
|
+
// Copiar templates como arquivos iniciais do projeto
|
|
173
|
+
const templateFiles = ['PROJECT.md', 'STATE.md', 'ROADMAP.md'];
|
|
174
|
+
for (const file of templateFiles) {
|
|
175
|
+
const src = path.join(templatesDir, file);
|
|
176
|
+
const dest = path.join(hefestoDir, file);
|
|
177
|
+
if (fs.existsSync(src)) {
|
|
178
|
+
fs.copyFileSync(src, dest);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Copiar pasta templates/ inteira para .hefesto/templates/
|
|
183
|
+
copyDir(templatesDir, path.join(hefestoDir, 'templates'));
|
|
184
|
+
|
|
185
|
+
// Criar config.json
|
|
186
|
+
fs.writeFileSync(
|
|
187
|
+
path.join(hefestoDir, 'config.json'),
|
|
188
|
+
JSON.stringify(createDefaultConfig(), null, 2) + '\n',
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
console.log(` ✅ .hefesto/ criado com scaffold do projeto.`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 2. Instalar em cada runtime
|
|
195
|
+
const runtimes = getSelectedRuntimes();
|
|
196
|
+
for (const runtime of runtimes) {
|
|
197
|
+
installRuntime(runtime);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
console.log(`\n ✅ Hefesto instalado com sucesso!`);
|
|
201
|
+
console.log(` Use /hefesto:init para configurar o projeto.\n`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function installRuntime(runtime) {
|
|
205
|
+
const runtimeDir = getRuntimeDir(runtime);
|
|
206
|
+
ensureDir(runtimeDir);
|
|
207
|
+
|
|
208
|
+
// Commands
|
|
209
|
+
const srcCommands = path.join(PKG_ROOT, 'commands', 'hefesto');
|
|
210
|
+
if (fs.existsSync(srcCommands)) {
|
|
211
|
+
const destCommands = getCommandsDestDir(runtime, runtimeDir);
|
|
212
|
+
copyDir(srcCommands, destCommands);
|
|
213
|
+
console.log(` ✅ Commands instalados em ${path.relative(process.cwd(), destCommands) || destCommands}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Skills
|
|
217
|
+
const srcSkills = path.join(PKG_ROOT, 'skills');
|
|
218
|
+
if (fs.existsSync(srcSkills)) {
|
|
219
|
+
const destSkills = getSkillsDestDir(runtime, runtimeDir);
|
|
220
|
+
copySkills(srcSkills, destSkills);
|
|
221
|
+
console.log(` ✅ Skills instaladas em ${path.relative(process.cwd(), destSkills) || destSkills}`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Hooks (apenas Claude Code por enquanto)
|
|
225
|
+
if (runtime === 'claude') {
|
|
226
|
+
installHooks(runtimeDir);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function getCommandsDestDir(_runtime, runtimeDir) {
|
|
231
|
+
// Claude: .claude/commands/hefesto/
|
|
232
|
+
// Gemini: .gemini/commands/hefesto/
|
|
233
|
+
// Codex: .codex/commands/hefesto/
|
|
234
|
+
return path.join(runtimeDir, 'commands', 'hefesto');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function getSkillsDestDir(_runtime, runtimeDir) {
|
|
238
|
+
// Claude: .claude/skills/
|
|
239
|
+
// Gemini: .gemini/skills/
|
|
240
|
+
// Codex: .codex/skills/
|
|
241
|
+
return path.join(runtimeDir, 'skills');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function copySkills(srcDir, destDir) {
|
|
245
|
+
ensureDir(destDir);
|
|
246
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
247
|
+
for (const entry of entries) {
|
|
248
|
+
if (entry.isDirectory() && entry.name.startsWith('hefesto-')) {
|
|
249
|
+
const srcSkill = path.join(srcDir, entry.name);
|
|
250
|
+
const destSkill = path.join(destDir, entry.name);
|
|
251
|
+
copyDir(srcSkill, destSkill);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ── Hooks ───────────────────────────────────────────────────────────────────
|
|
257
|
+
|
|
258
|
+
function installHooks(runtimeDir) {
|
|
259
|
+
const srcHooks = path.join(PKG_ROOT, 'hooks');
|
|
260
|
+
const destHooks = path.join(runtimeDir, 'hooks');
|
|
261
|
+
|
|
262
|
+
// Copiar hooks
|
|
263
|
+
ensureDir(destHooks);
|
|
264
|
+
for (const file of ['hefesto-statusline.cjs', 'hefesto-check-update.cjs']) {
|
|
265
|
+
const src = path.join(srcHooks, file);
|
|
266
|
+
if (fs.existsSync(src)) {
|
|
267
|
+
fs.copyFileSync(src, path.join(destHooks, file));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
console.log(` ✅ Hooks instalados em ${path.relative(process.cwd(), destHooks) || destHooks}`);
|
|
271
|
+
|
|
272
|
+
// Registrar hooks em settings.json
|
|
273
|
+
const settingsPath = path.join(runtimeDir, 'settings.json');
|
|
274
|
+
let settings = {};
|
|
275
|
+
if (fs.existsSync(settingsPath)) {
|
|
276
|
+
try {
|
|
277
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
278
|
+
} catch (_) {}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const hooksDir = destHooks.replace(/\\/g, '/');
|
|
282
|
+
const statuslineCmd = `node "${hooksDir}/hefesto-statusline.cjs"`;
|
|
283
|
+
const checkUpdateCmd = `node "${hooksDir}/hefesto-check-update.cjs"`;
|
|
284
|
+
|
|
285
|
+
// Statusline
|
|
286
|
+
settings.statusLine = {
|
|
287
|
+
type: 'command',
|
|
288
|
+
command: statuslineCmd,
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// SessionStart hook (check-update)
|
|
292
|
+
if (!settings.hooks) settings.hooks = {};
|
|
293
|
+
if (!settings.hooks.SessionStart) settings.hooks.SessionStart = [];
|
|
294
|
+
|
|
295
|
+
// Remover hook hefesto anterior se existir
|
|
296
|
+
settings.hooks.SessionStart = settings.hooks.SessionStart.filter(
|
|
297
|
+
h => !JSON.stringify(h).includes('hefesto-check-update'),
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
settings.hooks.SessionStart.push({
|
|
301
|
+
matcher: 'startup',
|
|
302
|
+
hooks: [{
|
|
303
|
+
type: 'command',
|
|
304
|
+
command: checkUpdateCmd,
|
|
305
|
+
}],
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
309
|
+
console.log(` ✅ Hooks registrados em settings.json`);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function uninstallHooks(runtimeDir) {
|
|
313
|
+
// Remover arquivos de hooks
|
|
314
|
+
const hooksDir = path.join(runtimeDir, 'hooks');
|
|
315
|
+
for (const file of ['hefesto-statusline.cjs', 'hefesto-check-update.cjs']) {
|
|
316
|
+
const hookPath = path.join(hooksDir, file);
|
|
317
|
+
if (fs.existsSync(hookPath)) {
|
|
318
|
+
fs.unlinkSync(hookPath);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Limpar settings.json
|
|
323
|
+
const settingsPath = path.join(runtimeDir, 'settings.json');
|
|
324
|
+
if (!fs.existsSync(settingsPath)) return;
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
328
|
+
|
|
329
|
+
// Remover statusline se é do hefesto
|
|
330
|
+
if (settings.statusLine?.command?.includes('hefesto-statusline')) {
|
|
331
|
+
delete settings.statusLine;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Remover hook de SessionStart do hefesto
|
|
335
|
+
if (settings.hooks?.SessionStart) {
|
|
336
|
+
settings.hooks.SessionStart = settings.hooks.SessionStart.filter(
|
|
337
|
+
h => !JSON.stringify(h).includes('hefesto-check-update'),
|
|
338
|
+
);
|
|
339
|
+
if (settings.hooks.SessionStart.length === 0) {
|
|
340
|
+
delete settings.hooks.SessionStart;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Limpar hooks vazio
|
|
345
|
+
if (settings.hooks && Object.keys(settings.hooks).length === 0) {
|
|
346
|
+
delete settings.hooks;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
350
|
+
console.log(` ✅ Hooks removidos de settings.json`);
|
|
351
|
+
} catch (_) {}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ── Uninstall ───────────────────────────────────────────────────────────────
|
|
355
|
+
|
|
356
|
+
function uninstallHefesto() {
|
|
357
|
+
console.log(banner);
|
|
358
|
+
console.log(` Desinstalando...\n`);
|
|
359
|
+
|
|
360
|
+
// 1. Remover .hefesto/
|
|
361
|
+
const hefestoDir = getHefestoDir();
|
|
362
|
+
if (removeIfExists(hefestoDir)) {
|
|
363
|
+
console.log(` ✅ .hefesto/ removido.`);
|
|
364
|
+
} else {
|
|
365
|
+
console.log(` ℹ️ .hefesto/ não encontrado.`);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 2. Remover de cada runtime
|
|
369
|
+
const runtimes = getSelectedRuntimes();
|
|
370
|
+
for (const runtime of runtimes) {
|
|
371
|
+
uninstallRuntime(runtime);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
console.log(`\n ✅ Hefesto desinstalado.\n`);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function uninstallRuntime(runtime) {
|
|
378
|
+
const runtimeDir = getRuntimeDir(runtime);
|
|
379
|
+
|
|
380
|
+
// Remover commands/hefesto/
|
|
381
|
+
const commandsDir = getCommandsDestDir(runtime, runtimeDir);
|
|
382
|
+
if (removeIfExists(commandsDir)) {
|
|
383
|
+
console.log(` ✅ Commands removidos de ${path.relative(process.cwd(), commandsDir) || commandsDir}`);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Remover skills hefesto-*
|
|
387
|
+
const skillsDir = getSkillsDestDir(runtime, runtimeDir);
|
|
388
|
+
if (fs.existsSync(skillsDir)) {
|
|
389
|
+
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
390
|
+
for (const entry of entries) {
|
|
391
|
+
if (entry.isDirectory() && entry.name.startsWith('hefesto-')) {
|
|
392
|
+
fs.rmSync(path.join(skillsDir, entry.name), { recursive: true });
|
|
393
|
+
console.log(` ✅ Skill ${entry.name} removida.`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Remover hooks (apenas Claude Code)
|
|
399
|
+
if (runtime === 'claude') {
|
|
400
|
+
uninstallHooks(runtimeDir);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// ── Main ────────────────────────────────────────────────────────────────────
|
|
405
|
+
|
|
406
|
+
if (hasUninstall) {
|
|
407
|
+
uninstallHefesto();
|
|
408
|
+
} else {
|
|
409
|
+
installHefesto();
|
|
410
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Inicializa o Hefesto no projeto atual. Use /hefesto:init para criar a estrutura .hefesto/ e começar a organizar o desenvolvimento."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Hefesto Init
|
|
6
|
+
|
|
7
|
+
Inicializa a estrutura `.hefesto/` no projeto atual.
|
|
8
|
+
|
|
9
|
+
## O que fazer
|
|
10
|
+
|
|
11
|
+
1. Verificar se `.hefesto/` já existe. Se existir, avisar o usuário e perguntar se quer reinicializar.
|
|
12
|
+
2. Perguntar ao usuário:
|
|
13
|
+
- Nome do projeto
|
|
14
|
+
- Descrição curta (2-3 frases)
|
|
15
|
+
- Valor central (a única coisa que DEVE funcionar)
|
|
16
|
+
- Restrições principais (stack, prazo, plataforma, etc.)
|
|
17
|
+
3. Criar a estrutura de diretórios:
|
|
18
|
+
```
|
|
19
|
+
.hefesto/
|
|
20
|
+
├── PROJECT.md
|
|
21
|
+
├── ROADMAP.md
|
|
22
|
+
├── STATE.md
|
|
23
|
+
├── config.json
|
|
24
|
+
└── features/
|
|
25
|
+
```
|
|
26
|
+
4. Preencher PROJECT.md com as respostas do usuário.
|
|
27
|
+
5. Gerar STATE.md inicial com posição "Inicializando".
|
|
28
|
+
6. Gerar ROADMAP.md vazio.
|
|
29
|
+
7. Gerar config.json com valores padrão:
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"version": "0.1.0",
|
|
33
|
+
"project": { "name": "", "language": "pt-BR" },
|
|
34
|
+
"runtime": "claude",
|
|
35
|
+
"feature": { "id_prefix": "FEAT", "counter": 0 },
|
|
36
|
+
"lifecycle": { "auto_update_state": true }
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
8. Informar o usuário que o projeto foi inicializado e sugerir `/hefesto:new-feature` para criar a primeira feature.
|
|
40
|
+
|
|
41
|
+
## Notas
|
|
42
|
+
|
|
43
|
+
- Todos os textos gerados devem ser em Português BR.
|
|
44
|
+
- O config.json deve ser atualizado com o nome do projeto informado pelo usuário.
|
|
45
|
+
- Se `.hefesto/` já existir e o usuário não quiser reinicializar, abortar sem modificar nada.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Cria uma nova feature no Hefesto. Use /hefesto:new-feature para definir uma nova feature com visão, fluxo do usuário, requisitos e fases de implementação."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Hefesto New Feature
|
|
6
|
+
|
|
7
|
+
Cria um novo documento de feature em `.hefesto/features/`.
|
|
8
|
+
|
|
9
|
+
## Pré-requisitos
|
|
10
|
+
|
|
11
|
+
Verificar se `.hefesto/` existe. Se não existir, sugerir `/hefesto:init` primeiro.
|
|
12
|
+
|
|
13
|
+
## O que fazer
|
|
14
|
+
|
|
15
|
+
1. Ler `.hefesto/templates/FEATURE.md` como base para o novo arquivo de feature.
|
|
16
|
+
2. Ler `.hefesto/config.json` para obter o próximo ID disponível.
|
|
17
|
+
3. Perguntar ao usuário:
|
|
18
|
+
- Título da feature (curto, descritivo)
|
|
19
|
+
- Visão (o que entrega e por que existe)
|
|
20
|
+
- Fluxo do usuário (passos que o usuário percorre)
|
|
21
|
+
- Requisitos principais (testáveis, centrados no usuário)
|
|
22
|
+
- O que está fora do escopo
|
|
23
|
+
4. Com base nas respostas, propor fases de implementação:
|
|
24
|
+
- Cada fase deve ser atômica (executável em uma sessão)
|
|
25
|
+
- Listar arquivos que serão criados/modificados
|
|
26
|
+
- Definir tarefas concretas e critérios de aceitação
|
|
27
|
+
5. Gerar o ID: `FEAT-NNN` onde NNN é o counter + 1, zero-padded.
|
|
28
|
+
6. Gerar o slug a partir do título (lowercase, hifenizado, max 40 chars).
|
|
29
|
+
7. Criar o arquivo `.hefesto/features/FEAT-NNN-slug.md` com o conteúdo.
|
|
30
|
+
8. Atualizar `.hefesto/config.json` incrementando o counter.
|
|
31
|
+
9. Atualizar `.hefesto/ROADMAP.md` adicionando a nova feature na tabela.
|
|
32
|
+
10. Atualizar `.hefesto/STATE.md` se for a primeira feature ou se nenhuma estiver ativa.
|
|
33
|
+
|
|
34
|
+
## Formato do arquivo
|
|
35
|
+
|
|
36
|
+
O arquivo segue o template narrativo unificado com frontmatter YAML:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
---
|
|
40
|
+
id: FEAT-NNN
|
|
41
|
+
title: "Título"
|
|
42
|
+
status: draft
|
|
43
|
+
created: YYYY-MM-DD
|
|
44
|
+
updated: YYYY-MM-DD
|
|
45
|
+
phases_total: N
|
|
46
|
+
phases_done: 0
|
|
47
|
+
---
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Seguido pelas seções: Visão, Fluxo do Usuário, Requisitos, Fora do Escopo, Implementação (com Fases), Notas Técnicas.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Mostra o estado atual do projeto Hefesto. Use /hefesto:status para ver progresso, features ativas, bloqueios e próximos passos."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Hefesto Status
|
|
6
|
+
|
|
7
|
+
Exibe o estado atual do projeto gerenciado pelo Hefesto.
|
|
8
|
+
|
|
9
|
+
## Pré-requisitos
|
|
10
|
+
|
|
11
|
+
Verificar se `.hefesto/` existe. Se não existir, informar que o projeto não foi inicializado e sugerir `/hefesto:init`.
|
|
12
|
+
|
|
13
|
+
## O que fazer
|
|
14
|
+
|
|
15
|
+
1. Ler `.hefesto/STATE.md` e exibir o conteúdo formatado.
|
|
16
|
+
2. Ler `.hefesto/ROADMAP.md` e calcular progresso geral.
|
|
17
|
+
3. Listar todas as features em `.hefesto/features/` com seus status (ler frontmatter de cada arquivo).
|
|
18
|
+
4. Apresentar um resumo ao usuário:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
📊 Estado do Projeto: [nome]
|
|
22
|
+
|
|
23
|
+
Progresso: [██████░░░░] 60% (3 de 5 features)
|
|
24
|
+
|
|
25
|
+
Feature ativa: FEAT-003 — Título (Fase 2 de 4)
|
|
26
|
+
|
|
27
|
+
Features:
|
|
28
|
+
✅ FEAT-001 — Título (done)
|
|
29
|
+
✅ FEAT-002 — Título (done)
|
|
30
|
+
🔄 FEAT-003 — Título (active — fase 2/4)
|
|
31
|
+
📋 FEAT-004 — Título (ready)
|
|
32
|
+
📝 FEAT-005 — Título (draft)
|
|
33
|
+
|
|
34
|
+
Bloqueios: Nenhum
|
|
35
|
+
|
|
36
|
+
Próximo passo: Continuar execução da Fase 2 de FEAT-003
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
5. Se houver bloqueios em STATE.md, destacá-los.
|
|
40
|
+
6. Sugerir próxima ação com base no estado atual.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Atualiza o Hefesto para a versão mais recente. Use /hefesto:update para atualizar commands, skills, hooks e templates sem perder o estado do projeto."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Hefesto Update
|
|
6
|
+
|
|
7
|
+
Atualiza o toolkit Hefesto para a versão mais recente do npm.
|
|
8
|
+
|
|
9
|
+
## Pré-requisitos
|
|
10
|
+
|
|
11
|
+
Verificar se `.hefesto/` existe. Se não existir, informar que o projeto não foi inicializado e sugerir `/hefesto:init`.
|
|
12
|
+
|
|
13
|
+
## O que fazer
|
|
14
|
+
|
|
15
|
+
1. Ler `.hefesto/config.json` e anotar a versão atual (`version`).
|
|
16
|
+
2. Executar o comando de atualização:
|
|
17
|
+
```bash
|
|
18
|
+
npx @lugom.io/hefesto@latest
|
|
19
|
+
```
|
|
20
|
+
3. Verificar o output do comando. Se houver erro, informar o usuário e sugerir ação corretiva.
|
|
21
|
+
4. Ler `.hefesto/config.json` novamente e comparar a versão com a anterior.
|
|
22
|
+
5. Informar o resultado ao usuário:
|
|
23
|
+
- Se atualizou: mostrar versão anterior → nova versão
|
|
24
|
+
- Se já estava na última versão: informar que está atualizado
|
|
25
|
+
|
|
26
|
+
## Notas
|
|
27
|
+
|
|
28
|
+
- O installer preserva `.hefesto/` existente (PROJECT.md, STATE.md, ROADMAP.md, features/, config.json).
|
|
29
|
+
- O que é atualizado: commands, skills, hooks, templates.
|
|
30
|
+
- Não usar `--global` a menos que o usuário peça explicitamente.
|
|
31
|
+
- Se o usuário pedir para atualizar um runtime específico (ex: `--gemini`), passar a flag correspondente.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Hefesto Update Checker
|
|
3
|
+
// Verifica novas versões em background no SessionStart
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const { spawn } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
|
|
11
|
+
const cacheDir = path.join(configDir, 'cache');
|
|
12
|
+
const cacheFile = path.join(cacheDir, 'hefesto-update-check.json');
|
|
13
|
+
|
|
14
|
+
// Garantir que cache dir existe
|
|
15
|
+
if (!fs.existsSync(cacheDir)) {
|
|
16
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Rodar check em background (não bloqueia a sessão)
|
|
20
|
+
const child = spawn(process.execPath, ['-e', `
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const { execSync } = require('child_process');
|
|
23
|
+
const cacheFile = ${JSON.stringify(cacheFile)};
|
|
24
|
+
|
|
25
|
+
let installed = '0.0.0';
|
|
26
|
+
try {
|
|
27
|
+
const pkg = JSON.parse(execSync('npm ls hefesto --json 2>/dev/null', {
|
|
28
|
+
encoding: 'utf8', timeout: 10000, windowsHide: true
|
|
29
|
+
}));
|
|
30
|
+
installed = pkg.dependencies?.hefesto?.version || '0.0.0';
|
|
31
|
+
} catch (_) {
|
|
32
|
+
// Se não conseguir detectar versão instalada, tentar package.json local
|
|
33
|
+
try {
|
|
34
|
+
const localPkg = JSON.parse(fs.readFileSync('node_modules/hefesto/package.json', 'utf8'));
|
|
35
|
+
installed = localPkg.version || '0.0.0';
|
|
36
|
+
} catch (_) {}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let latest = null;
|
|
40
|
+
try {
|
|
41
|
+
latest = execSync('npm view hefesto version', {
|
|
42
|
+
encoding: 'utf8', timeout: 10000, windowsHide: true
|
|
43
|
+
}).trim();
|
|
44
|
+
} catch (_) {}
|
|
45
|
+
|
|
46
|
+
const result = {
|
|
47
|
+
update_available: latest && installed !== latest && latest !== '0.0.0',
|
|
48
|
+
installed,
|
|
49
|
+
latest: latest || 'unknown',
|
|
50
|
+
checked: Math.floor(Date.now() / 1000),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
fs.writeFileSync(cacheFile, JSON.stringify(result));
|
|
54
|
+
`], {
|
|
55
|
+
stdio: 'ignore',
|
|
56
|
+
windowsHide: true,
|
|
57
|
+
detached: true,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
child.unref();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Hefesto Statusline
|
|
3
|
+
// Mostra: ⚒ HEFESTO | model | directory | context usage
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
|
|
9
|
+
let input = '';
|
|
10
|
+
const stdinTimeout = setTimeout(() => process.exit(0), 3000);
|
|
11
|
+
process.stdin.setEncoding('utf8');
|
|
12
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
13
|
+
process.stdin.on('end', () => {
|
|
14
|
+
clearTimeout(stdinTimeout);
|
|
15
|
+
try {
|
|
16
|
+
const data = JSON.parse(input);
|
|
17
|
+
const model = data.model?.display_name || 'Claude';
|
|
18
|
+
const dir = data.workspace?.current_dir || process.cwd();
|
|
19
|
+
const session = data.session_id || '';
|
|
20
|
+
const remaining = data.context_window?.remaining_percentage;
|
|
21
|
+
|
|
22
|
+
// Context window (normalizado para contexto utilizável)
|
|
23
|
+
const AUTO_COMPACT_BUFFER_PCT = 16.5;
|
|
24
|
+
let ctx = '';
|
|
25
|
+
if (remaining != null) {
|
|
26
|
+
const usableRemaining = Math.max(0, ((remaining - AUTO_COMPACT_BUFFER_PCT) / (100 - AUTO_COMPACT_BUFFER_PCT)) * 100);
|
|
27
|
+
const used = Math.max(0, Math.min(100, Math.round(100 - usableRemaining)));
|
|
28
|
+
|
|
29
|
+
// Bridge file para o context-monitor
|
|
30
|
+
if (session) {
|
|
31
|
+
try {
|
|
32
|
+
const bridgePath = path.join(os.tmpdir(), `hefesto-ctx-${session}.json`);
|
|
33
|
+
fs.writeFileSync(bridgePath, JSON.stringify({
|
|
34
|
+
session_id: session,
|
|
35
|
+
remaining_percentage: remaining,
|
|
36
|
+
used_pct: used,
|
|
37
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
38
|
+
}));
|
|
39
|
+
} catch (_) {}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Barra de progresso (10 segmentos)
|
|
43
|
+
const filled = Math.floor(used / 10);
|
|
44
|
+
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
45
|
+
|
|
46
|
+
if (used < 50) {
|
|
47
|
+
ctx = ` \x1b[32m${bar} ${used}%\x1b[0m`;
|
|
48
|
+
} else if (used < 65) {
|
|
49
|
+
ctx = ` \x1b[33m${bar} ${used}%\x1b[0m`;
|
|
50
|
+
} else if (used < 80) {
|
|
51
|
+
ctx = ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
|
|
52
|
+
} else {
|
|
53
|
+
ctx = ` \x1b[5;31m💀 ${bar} ${used}%\x1b[0m`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Update disponível?
|
|
58
|
+
let updateMsg = '';
|
|
59
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
|
|
60
|
+
const cacheFile = path.join(configDir, 'cache', 'hefesto-update-check.json');
|
|
61
|
+
if (fs.existsSync(cacheFile)) {
|
|
62
|
+
try {
|
|
63
|
+
const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
64
|
+
if (cache.update_available) {
|
|
65
|
+
updateMsg = '\x1b[33m⬆ npx @lugom.io/hefesto\x1b[0m │ ';
|
|
66
|
+
}
|
|
67
|
+
} catch (_) {}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const dirname = path.basename(dir);
|
|
71
|
+
process.stdout.write(`${updateMsg}\x1b[1;31m⚒ HEFESTO\x1b[0m │ \x1b[2m${model}\x1b[0m │ \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
72
|
+
} catch (_) {
|
|
73
|
+
// Falha silenciosa
|
|
74
|
+
}
|
|
75
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lugom.io/hefesto",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A meta-prompting, context engineering and spec-driven development system for Claude Code, Gemini and Codex by lugom.io.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"hefesto": "./bin/install.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --test tests/**/*.test.js"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"bin/",
|
|
17
|
+
"templates/",
|
|
18
|
+
"commands/",
|
|
19
|
+
"skills/",
|
|
20
|
+
"hooks/",
|
|
21
|
+
"agents/"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"claude",
|
|
25
|
+
"claude-code",
|
|
26
|
+
"ai",
|
|
27
|
+
"meta-prompting",
|
|
28
|
+
"context-engineering",
|
|
29
|
+
"spec-driven-development",
|
|
30
|
+
"gemini",
|
|
31
|
+
"gemini-cli",
|
|
32
|
+
"codex",
|
|
33
|
+
"codex-cli"
|
|
34
|
+
],
|
|
35
|
+
"author": "lugom.io",
|
|
36
|
+
"license": "MIT"
|
|
37
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hefesto-context
|
|
3
|
+
description: Conhecimento sobre a estrutura e convenções do Hefesto. Use sempre que o projeto tiver um diretório .hefesto/, quando o usuário mencionar features, specs, stories, roadmap ou estado do projeto no contexto do Hefesto, ou quando precisar entender como o .hefesto/ organiza o desenvolvimento.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hefesto Context
|
|
7
|
+
|
|
8
|
+
O Hefesto é um toolkit spec-driven + story-driven que organiza o desenvolvimento através de documentos narrativos unificados chamados **features**.
|
|
9
|
+
|
|
10
|
+
## Estrutura `.hefesto/`
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
.hefesto/
|
|
14
|
+
├── PROJECT.md # Visão, valor central, restrições do projeto
|
|
15
|
+
├── ROADMAP.md # Lista de features com status e progresso
|
|
16
|
+
├── STATE.md # Memória viva — posição atual, decisões, bloqueios (~80 linhas)
|
|
17
|
+
├── config.json # Configuração (counters de ID, runtime, preferências)
|
|
18
|
+
└── features/ # Documentos narrativos unificados
|
|
19
|
+
└── FEAT-NNN-slug.md # Uma feature por arquivo
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
Cada feature é um documento narrativo que combina **spec** (O QUÊ) e **stories** (COMO) em um único arquivo:
|
|
25
|
+
|
|
26
|
+
- **Visão** — o que entrega e por que existe
|
|
27
|
+
- **Fluxo do Usuário** — passos que o usuário percorre
|
|
28
|
+
- **Requisitos** — checklist testável (REQ-01, REQ-02, ...)
|
|
29
|
+
- **Fora do Escopo** — exclusões explícitas
|
|
30
|
+
- **Implementação** — dividida em **Fases** (cada fase = uma story atômica)
|
|
31
|
+
- Arquivos a criar/modificar
|
|
32
|
+
- Tarefas concretas
|
|
33
|
+
- Critérios de aceitação
|
|
34
|
+
|
|
35
|
+
## IDs e Naming
|
|
36
|
+
|
|
37
|
+
- **Feature ID**: `FEAT-NNN` (zero-padded, sequencial)
|
|
38
|
+
- **Arquivo**: `FEAT-NNN-slug.md` (slug = título lowercase hifenizado, max 40 chars)
|
|
39
|
+
- **Counter**: mantido em `config.json` → `feature.counter`
|
|
40
|
+
|
|
41
|
+
## Status
|
|
42
|
+
|
|
43
|
+
- `draft` — em definição
|
|
44
|
+
- `ready` — pronta para execução
|
|
45
|
+
- `active` — em andamento
|
|
46
|
+
- `done` — completa e verificada
|
|
47
|
+
- `blocked` — bloqueada por dependência
|
|
48
|
+
|
|
49
|
+
## STATE.md
|
|
50
|
+
|
|
51
|
+
Memória viva do projeto. Máximo ~80 linhas. Contém:
|
|
52
|
+
- Posição atual (features feitas vs total)
|
|
53
|
+
- Feature e fase ativa
|
|
54
|
+
- Decisões recentes
|
|
55
|
+
- Bloqueios
|
|
56
|
+
- Informação de continuidade (última sessão, onde parou, como retomar)
|
|
57
|
+
|
|
58
|
+
## Outputs
|
|
59
|
+
|
|
60
|
+
Outputs reais (código, documentos, manifestos) vão para o projeto (src/, docs/, etc.). O `.hefesto/` apenas rastreia o que foi produzido e onde foi colocado.
|
|
61
|
+
|
|
62
|
+
## Commands disponíveis
|
|
63
|
+
|
|
64
|
+
- `/hefesto:init` — Inicializa .hefesto/ no projeto
|
|
65
|
+
- `/hefesto:new-feature` — Cria nova feature
|
|
66
|
+
- `/hefesto:status` — Mostra estado do projeto
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: { { FEATURE_ID } }
|
|
3
|
+
title: "{{FEATURE_TITLE}}"
|
|
4
|
+
status: draft
|
|
5
|
+
created: { { DATE } }
|
|
6
|
+
updated: { { DATE } }
|
|
7
|
+
phases_total: 0
|
|
8
|
+
phases_done: 0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# {{FEATURE_ID}}: {{FEATURE_TITLE}}
|
|
12
|
+
|
|
13
|
+
## Visão
|
|
14
|
+
|
|
15
|
+
{{FEATURE_VISION}}
|
|
16
|
+
|
|
17
|
+
## Fluxo do Usuário
|
|
18
|
+
|
|
19
|
+
1. {{USER_FLOW_STEP_1}}
|
|
20
|
+
2. {{USER_FLOW_STEP_2}}
|
|
21
|
+
3. {{USER_FLOW_STEP_3}}
|
|
22
|
+
|
|
23
|
+
## Requisitos
|
|
24
|
+
|
|
25
|
+
- [ ] **REQ-01**: {{REQUIREMENT_1}}
|
|
26
|
+
- [ ] **REQ-02**: {{REQUIREMENT_2}}
|
|
27
|
+
|
|
28
|
+
## Fora do Escopo
|
|
29
|
+
|
|
30
|
+
- {{EXCLUSION_1}}
|
|
31
|
+
|
|
32
|
+
## Implementação
|
|
33
|
+
|
|
34
|
+
### Fase 1: {{PHASE_1_NAME}}
|
|
35
|
+
|
|
36
|
+
**Arquivos:**
|
|
37
|
+
|
|
38
|
+
- `{{FILE_PATH}}` — {{FILE_DESCRIPTION}}
|
|
39
|
+
|
|
40
|
+
**Tarefas:**
|
|
41
|
+
|
|
42
|
+
- [ ] {{TASK_1}}
|
|
43
|
+
- [ ] {{TASK_2}}
|
|
44
|
+
|
|
45
|
+
**Critérios de Aceitação:**
|
|
46
|
+
|
|
47
|
+
- [ ] {{ACCEPTANCE_CRITERIA_1}}
|
|
48
|
+
- [ ] {{ACCEPTANCE_CRITERIA_2}}
|
|
49
|
+
|
|
50
|
+
## Notas Técnicas
|
|
51
|
+
|
|
52
|
+
{{TECHNICAL_NOTES}}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
## O Que É
|
|
4
|
+
|
|
5
|
+
{{PROJECT_DESCRIPTION}}
|
|
6
|
+
|
|
7
|
+
## Valor Central
|
|
8
|
+
|
|
9
|
+
{{CORE_VALUE}}
|
|
10
|
+
|
|
11
|
+
## Contexto
|
|
12
|
+
|
|
13
|
+
{{CONTEXT}}
|
|
14
|
+
|
|
15
|
+
## Restrições
|
|
16
|
+
|
|
17
|
+
- **Stack**: {{STACK_CONSTRAINT}}
|
|
18
|
+
- **Prazo**: {{DEADLINE_CONSTRAINT}}
|
|
19
|
+
|
|
20
|
+
## Decisões
|
|
21
|
+
|
|
22
|
+
| Decisão | Justificativa | Resultado |
|
|
23
|
+
| ------- | ------------- | --------- |
|
|
24
|
+
| — | — | — |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
_Última atualização: {{DATE}}_
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
## Visão Geral
|
|
4
|
+
|
|
5
|
+
{{PROJECT_NAME}} — {{PROJECT_DESCRIPTION}}
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
| ID | Título | Status | Fases | Progresso |
|
|
10
|
+
| --- | ------ | ------ | ----- | --------- |
|
|
11
|
+
| — | — | — | — | — |
|
|
12
|
+
|
|
13
|
+
## Legenda
|
|
14
|
+
|
|
15
|
+
- `draft` — Em definição
|
|
16
|
+
- `ready` — Pronta para execução
|
|
17
|
+
- `active` — Em andamento
|
|
18
|
+
- `done` — Completa e verificada
|
|
19
|
+
- `blocked` — Bloqueada
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
_Atualizado automaticamente ao concluir features._
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Estado do Projeto
|
|
2
|
+
|
|
3
|
+
## Referência
|
|
4
|
+
|
|
5
|
+
**Projeto:** {{PROJECT_NAME}}
|
|
6
|
+
**Valor central:** {{CORE_VALUE}}
|
|
7
|
+
**Foco atual:** {{CURRENT_FOCUS}}
|
|
8
|
+
|
|
9
|
+
## Posição Atual
|
|
10
|
+
|
|
11
|
+
- Features: 0 de 0 completas
|
|
12
|
+
- Status: Inicializando
|
|
13
|
+
- Última atividade: {{DATE}} — Projeto inicializado
|
|
14
|
+
|
|
15
|
+
Progresso: [░░░░░░░░░░] 0%
|
|
16
|
+
|
|
17
|
+
## Feature Ativa
|
|
18
|
+
|
|
19
|
+
Nenhuma.
|
|
20
|
+
|
|
21
|
+
## Decisões Recentes
|
|
22
|
+
|
|
23
|
+
Nenhuma.
|
|
24
|
+
|
|
25
|
+
## Bloqueios
|
|
26
|
+
|
|
27
|
+
Nenhum.
|
|
28
|
+
|
|
29
|
+
## Continuidade
|
|
30
|
+
|
|
31
|
+
- Última sessão: {{DATE}}
|
|
32
|
+
- Parou em: Inicialização do projeto
|
|
33
|
+
- Retomar: Criar primeira feature com /hefesto:new-feature
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
_Manter abaixo de 80 linhas. É um resumo, não um arquivo._
|