grimoire-framework 1.7.0 → 1.7.1

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.
@@ -7,8 +7,8 @@
7
7
  # - SHA256 hashes for change detection
8
8
  # - File types for categorization
9
9
  #
10
- version: 1.7.0
11
- generated_at: "2026-02-22T18:11:23.264Z"
10
+ version: 1.7.1
11
+ generated_at: "2026-02-22T18:21:15.311Z"
12
12
  generator: scripts/generate-install-manifest.js
13
13
  file_count: 1011
14
14
  files:
@@ -227,6 +227,117 @@ function regEscape(s) {
227
227
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
228
228
  }
229
229
 
230
+ // ── Live Status block ──────────────────────────────────────────────────
231
+ const STATUS_START = '<!-- grimoire-MANAGED-START: live-status -->';
232
+ const STATUS_END = '<!-- grimoire-MANAGED-END: live-status -->';
233
+
234
+ function loadActiveStories(grimoireDir) {
235
+ const storiesDir = path.join(grimoireDir, 'stories');
236
+ if (!fs.existsSync(storiesDir)) return { active: [], backlog: [] };
237
+ const stories = fs.readdirSync(storiesDir)
238
+ .filter(f => f.endsWith('.json'))
239
+ .map(f => { try { return JSON.parse(fs.readFileSync(path.join(storiesDir, f), 'utf8')); } catch (_) { return null; } })
240
+ .filter(Boolean);
241
+ return {
242
+ active: stories.filter(s => s.status === 'in_progress'),
243
+ backlog: stories.filter(s => s.status === 'backlog'),
244
+ };
245
+ }
246
+
247
+ function timeSpentLabel(story) {
248
+ if (!story.startedAt) return '';
249
+ const ms = new Date() - new Date(story.startedAt);
250
+ const h = Math.floor(ms / 3600000);
251
+ const m = Math.floor((ms % 3600000) / 60000);
252
+ return ` ⏱ ${h}h${m}min`;
253
+ }
254
+
255
+ function loadRagStatus(grimoireDir) {
256
+ const cfgF = path.join(grimoireDir, 'config.yaml');
257
+ if (!fs.existsSync(cfgF)) return null;
258
+ const lines = fs.readFileSync(cfgF, 'utf8').split('\n');
259
+ const get = (k) => { const l = lines.find(l => l.startsWith(k + ':')); return l ? l.split(':')[1]?.trim() : null; };
260
+ return get('embedding_provider') || null;
261
+ }
262
+
263
+ function buildLiveStatusBlock(grimoireDir, entries) {
264
+ const now = new Date();
265
+ const dateStr = now.toISOString().replace('T', ' ').slice(0, 16);
266
+ const { active, backlog } = loadActiveStories(grimoireDir);
267
+ const ragProvider = loadRagStatus(grimoireDir);
268
+
269
+ // Count memories
270
+ const todayKey = now.toISOString().split('T')[0];
271
+ const todayCount = entries.filter(e => e.date === todayKey).length;
272
+ const totalCount = entries.length;
273
+
274
+ // Detect sprint from stories or memory tags
275
+ const sprintMem = entries.filter(e => /sprint/i.test(e.content)).slice(-1)[0];
276
+
277
+ const block = [STATUS_START];
278
+ block.push('');
279
+ block.push('## 🟢 Grimoire Ativo');
280
+ block.push('');
281
+ block.push('> Este bloco é auto-gerado pelo `grimoire context update` e confirma que o Grimoire Framework está ativo neste projeto.');
282
+ block.push('');
283
+ block.push('```');
284
+ block.push(`Data: ${dateStr}`);
285
+
286
+ if (active.length) {
287
+ block.push(`\nAtividades em andamento (${active.length}):`);
288
+ active.forEach(s => block.push(` [${s.id}] ${s.title}${timeSpentLabel(s)}`));
289
+ } else {
290
+ block.push(`\nAtividades: nenhuma em andamento`);
291
+ }
292
+
293
+ if (backlog.length) {
294
+ block.push(`Backlog: ${backlog.length} atividade(s) aguardando`);
295
+ }
296
+
297
+ const ragLabel = ragProvider && ragProvider !== 'tfidf'
298
+ ? `ativo (${ragProvider})`
299
+ : 'tfidf (sem embedding — rode grimoire setup rag)';
300
+ block.push(`\nMemória: ${totalCount} total · ${todayCount} hoje`);
301
+ block.push(`RAG: ${ragLabel}`);
302
+ block.push(`\nComandos úteis:`);
303
+ block.push(` grimoire → dashboard kanban`);
304
+ block.push(` grimoire memory search "query" → busca semântica`);
305
+ block.push(` grimoire context update → atualizar este bloco`);
306
+ block.push(` *status → verificar estado no chat`);
307
+ block.push('```');
308
+ block.push('');
309
+ block.push(STATUS_END);
310
+ return block.join('\n');
311
+ }
312
+
313
+ function injectLiveStatus(grimoireDir, entries) {
314
+ const cwd = process.cwd();
315
+ const candidates = [
316
+ path.join(cwd, 'GEMINI.md'),
317
+ path.join(path.dirname(grimoireDir), 'GEMINI.md'),
318
+ ];
319
+ const geminiPath = candidates.find(p => fs.existsSync(p));
320
+ if (!geminiPath) return false;
321
+
322
+ const original = fs.readFileSync(geminiPath, 'utf8');
323
+ const newBlock = buildLiveStatusBlock(grimoireDir, entries);
324
+
325
+ let updated;
326
+ if (original.includes(STATUS_START)) {
327
+ const re = new RegExp(`${regEscape(STATUS_START)}[\\s\\S]*?${regEscape(STATUS_END)}`, 'g');
328
+ updated = original.replace(re, newBlock);
329
+ } else {
330
+ // Insert at the very end (after all managed blocks)
331
+ updated = original.trimEnd() + '\n\n' + newBlock + '\n';
332
+ }
333
+
334
+ if (updated !== original) {
335
+ fs.writeFileSync(geminiPath, updated, 'utf8');
336
+ return true;
337
+ }
338
+ return false;
339
+ }
340
+
230
341
  // ── Core update logic ─────────────────────────────────────────────────────────
231
342
  function doUpdate(grimoireDir, silent = false) {
232
343
  const contextDir = getContextDir(grimoireDir);
@@ -255,16 +366,19 @@ function doUpdate(grimoireDir, silent = false) {
255
366
  fs.writeFileSync(path.join(contextDir, 'pinned.md'), pinnedLines.join('\n'), 'utf8');
256
367
  }
257
368
 
258
- // Inject GEMINI.md
369
+ // Inject GEMINI.md memory-context block
259
370
  const injected = injectIntoGeminiMd(grimoireDir, entries);
260
371
 
372
+ // Inject live-status block (separate, always updated)
373
+ const statusInjected = injectLiveStatus(grimoireDir, entries);
374
+
261
375
  if (!silent) {
262
376
  console.log('\n✅ Contexto atualizado!\n');
263
377
  console.log(` 📄 .grimoire/context/CONTEXT.md`);
264
378
  if (dec) console.log(` ✅ .grimoire/context/decisions.md`);
265
379
  if (pat) console.log(` 🔧 .grimoire/context/patterns.md`);
266
380
  if (pinned.length) console.log(` 📌 .grimoire/context/pinned.md`);
267
- if (injected) console.log(` 🔮 GEMINI.md atualizado com bloco memory-context`);
381
+ if (injected || statusInjected) console.log(` 🟢 GEMINI.md bloco live-status + memory-context atualizados`);
268
382
  console.log(`\n ${entries.length} entradas indexadas`);
269
383
  console.log(` grimoire context show ← ver o resultado\n`);
270
384
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grimoire-framework",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Grimoire: AI-Orchestrated System for Full Stack Development - Core Framework",
5
5
  "publishConfig": {
6
6
  "access": "public"