grimoire-framework 1.0.2 β 1.0.4
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/.grimoire/install-manifest.yaml +2 -2
- package/.grimoire/memory/README.md +13 -0
- package/.grimoire/memory/entities/context.md +19 -0
- package/.grimoire/memory/entities/decisions.md +17 -0
- package/.grimoire/memory/entities/patterns.md +20 -0
- package/.grimoire/memory/sessions/2026-02-22.json +9 -0
- package/.grimoire/memory/sessions/archived/2026-02-22.jsonl +3 -0
- package/bin/commands/memory.js +215 -0
- package/bin/commands/metrics.js +107 -0
- package/bin/grimoire-cli.js +103 -0
- package/bin/grimoire-ids.js +2 -2
- package/bin/grimoire-minimal.js +1 -1
- package/bin/grimoire.js +1118 -1118
- package/bin/modules/env-config.js +2 -2
- package/bin/modules/mcp-installer.js +1 -1
- package/bin/utils/install-errors.js +1 -1
- package/bin/utils/install-transaction.js +2 -2
- package/bin/utils/pro-detector.js +110 -110
- package/package.json +158 -158
- package/packages/gemini-grimoire-extension/commands/grimoire-agents.js +2 -2
- package/packages/gemini-grimoire-extension/commands/grimoire-master.js +1 -1
- package/packages/gemini-grimoire-extension/commands/grimoire-status.js +2 -2
- package/packages/gemini-grimoire-extension/commands/grimoire-validate.js +2 -2
- package/packages/gemini-grimoire-extension/commands/lib/agent-launcher.js +147 -147
- package/packages/gemini-grimoire-extension/extension.json +2 -2
- package/packages/gemini-grimoire-extension/gemini-extension.json +2 -2
- package/packages/gemini-grimoire-extension/hooks/hooks.json +2 -2
- package/packages/grimoire-install/.releaserc.json +1 -1
- package/packages/grimoire-install/CHANGELOG.md +1 -1
- package/packages/grimoire-install/README.md +2 -2
- package/packages/grimoire-install/bin/edmcp.js +1 -1
- package/packages/grimoire-install/bin/grimoire-install.js +1 -1
- package/packages/grimoire-install/jest.config.js +1 -1
- package/packages/grimoire-install/package.json +2 -2
- package/packages/grimoire-install/src/edmcp/index.js +1 -1
- package/packages/grimoire-install/src/installer.js +2 -2
- package/packages/grimoire-pro-cli/bin/grimoire-pro.js +2 -2
- package/packages/grimoire-pro-cli/package.json +2 -2
- package/packages/grimoire-pro-cli/src/recover.js +1 -1
- package/packages/installer/package.json +1 -1
- package/packages/installer/src/__tests__/performance-benchmark.js +2 -2
- package/packages/installer/src/config/configure-environment.js +2 -2
- package/packages/installer/src/config/ide-configs.js +2 -2
- package/packages/installer/src/config/templates/core-config-template.js +2 -2
- package/packages/installer/src/config/templates/env-template.js +2 -2
- package/packages/installer/src/config/validation/config-validator.js +1 -1
- package/packages/installer/src/detection/detect-project-type.js +2 -2
- package/packages/installer/src/installer/brownfield-upgrader.js +2 -2
- package/packages/installer/src/installer/grimoire-core-installer.js +2 -2
- package/packages/installer/src/installer/manifest-signature.js +2 -2
- package/packages/installer/src/installer/post-install-validator.js +2 -2
- package/packages/installer/src/installer/squad-installer.js +109 -0
- package/packages/installer/src/merger/index.js +1 -1
- package/packages/installer/src/merger/parsers/markdown-section-parser.js +1 -1
- package/packages/installer/src/merger/strategies/env-merger.js +1 -1
- package/packages/installer/src/merger/strategies/markdown-merger.js +1 -1
- package/packages/installer/src/merger/types.js +1 -1
- package/packages/installer/src/pro/pro-scaffolder.js +2 -2
- package/packages/installer/src/updater/index.js +2 -2
- package/packages/installer/src/utils/grimoire-colors.js +1 -1
- package/packages/installer/src/wizard/i18n.js +2 -2
- package/packages/installer/src/wizard/ide-config-generator.js +2 -2
- package/packages/installer/src/wizard/ide-selector.js +1 -1
- package/packages/installer/src/wizard/index.js +28 -36
- package/packages/installer/src/wizard/pro-setup.js +2 -2
- package/packages/installer/src/wizard/questions.js +20 -15
- package/packages/installer/src/wizard/validation/index.js +1 -1
- package/packages/installer/src/wizard/validation/report-generator.js +1 -1
- package/packages/installer/src/wizard/validation/troubleshooting-system.js +2 -2
- package/packages/installer/src/wizard/validation/validators/config-validator.js +2 -2
- package/packages/installer/src/wizard/validation/validators/file-structure-validator.js +1 -1
- package/packages/installer/src/wizard/wizard.js +2 -2
- package/packages/installer/tests/integration/environment-configuration.test.js +2 -2
- package/packages/installer/tests/integration/wizard-detection.test.js +2 -2
- package/packages/installer/tests/unit/config-validator.test.js +1 -1
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +2 -2
- package/packages/installer/tests/unit/env-template.test.js +2 -2
- package/packages/installer/tests/unit/merger/env-merger.test.js +1 -1
- package/packages/installer/tests/unit/merger/markdown-merger.test.js +1 -1
- package/scripts/check-markdown-links.py +352 -352
- package/scripts/code-intel-health-check.js +1 -1
- package/scripts/dashboard-parallel-dev.sh +1 -1
- package/scripts/dashboard-parallel-phase3.sh +1 -1
- package/scripts/dashboard-parallel-phase4.sh +1 -1
- package/scripts/ensure-manifest.js +1 -1
- package/scripts/generate-install-manifest.js +2 -2
- package/scripts/install-monitor-hooks.sh +2 -2
- package/scripts/package-synapse.js +2 -2
- package/scripts/semantic-lint.js +1 -1
- package/scripts/sign-manifest.sh +2 -2
- package/scripts/validate-manifest.js +2 -2
- package/scripts/validate-package-completeness.js +2 -2
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 1.0.
|
|
11
|
-
generated_at: "2026-02-
|
|
10
|
+
version: 1.0.4
|
|
11
|
+
generated_at: "2026-02-22T10:43:42.050Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
13
|
file_count: 1011
|
|
14
14
|
files:
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Grimoire Memory System
|
|
2
|
+
|
|
3
|
+
Este diretΓ³rio armazena o contexto persistente do projeto, permitindo que os agentes mantenham conhecimento entre diferentes sessΓ΅es.
|
|
4
|
+
|
|
5
|
+
## Estrutura
|
|
6
|
+
- `sessions/`: Logs de eventos e interaΓ§Γ΅es importantes de cada dia.
|
|
7
|
+
- `entities/`: Conhecimento estruturado sobre o projeto.
|
|
8
|
+
- `decisions.md`: Registro de decisΓ΅es tΓ©cnicas (ADR-like).
|
|
9
|
+
- `context.md`: VisΓ£o geral do estado atual do projeto.
|
|
10
|
+
- `patterns.md`: PadrΓ΅es de cΓ³digo e preferΓͺncias identificadas.
|
|
11
|
+
|
|
12
|
+
## Como Funciona
|
|
13
|
+
O Grimoire CLI injeta automaticamente o conteΓΊdo relevante destes arquivos no contexto dos agentes durante a ativaΓ§Γ£o.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
domain: project
|
|
3
|
+
type: overview
|
|
4
|
+
tags: [context, status, goals]
|
|
5
|
+
last_updated: 2026-02-22
|
|
6
|
+
priority: medium
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Project Context
|
|
10
|
+
|
|
11
|
+
VisΓ£o geral do estado atual e objetivos do projeto.
|
|
12
|
+
|
|
13
|
+
## Objetivo Atual
|
|
14
|
+
- Melhorar o Grimoire Framework utilizando a metodologia AIOS.
|
|
15
|
+
|
|
16
|
+
## Estado do Sistema
|
|
17
|
+
- Squads bΓ‘sicos implementados.
|
|
18
|
+
- Instalador atualizado para suportar seleΓ§Γ£o de squads.
|
|
19
|
+
- Sistema de memΓ³ria otimizado com JSONL e Async I/O.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
domain: management
|
|
3
|
+
type: technical-decisions
|
|
4
|
+
tags: [architecture, strategy, roadmap]
|
|
5
|
+
last_updated: 2026-02-22
|
|
6
|
+
priority: high
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Decisions Log
|
|
10
|
+
|
|
11
|
+
Este arquivo registra as decisΓ΅es tΓ©cnicas importantes tomadas durante o desenvolvimento do projeto.
|
|
12
|
+
|
|
13
|
+
| Data | DecisΓ£o | Contexto | Status |
|
|
14
|
+
|------|---------|----------|--------|
|
|
15
|
+
| 2026-02-22 | ImplementaΓ§Γ£o do Sistema de Squads | OrganizaΓ§Γ£o modular de agentes | β
ConcluΓdo |
|
|
16
|
+
| 2026-02-22 | MigraΓ§Γ£o para JSONL na MemΓ³ria | OtimizaΓ§Γ£o de performance de I/O | β
ConcluΓdo |
|
|
17
|
+
| 2026-02-22 | IntegraΓ§Γ£o Jira via MCP | Uso de Model Context Protocol para tarefas Jira | β
ConcluΓdo |
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
domain: development
|
|
3
|
+
type: standards
|
|
4
|
+
tags: [coding-style, conventions, patterns]
|
|
5
|
+
last_updated: 2026-02-22
|
|
6
|
+
priority: medium
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Code Patterns & Preferences
|
|
10
|
+
|
|
11
|
+
PadrΓ΅es identificados e preferΓͺncias de desenvolvimento.
|
|
12
|
+
|
|
13
|
+
## PadrΓ΅es de CΓ³digo
|
|
14
|
+
- **Async-First**: Todas as novas funcionalidades de I/O devem ser assΓncronas.
|
|
15
|
+
- **JSONL for Logs**: Usar JSON Lines para registros de eventos contΓnuos.
|
|
16
|
+
- **YAML Frontmatter**: ObrigatΓ³rio em todos os arquivos de conhecimento da memΓ³ria.
|
|
17
|
+
- **Squad Naming**: Usar nomes curtos em minΓΊsculas (ex: `fullstack`, `devops`) para pastas e IDs.
|
|
18
|
+
|
|
19
|
+
## PreferΓͺncias
|
|
20
|
+
- Priorizar simplicidade e performance bruta no CLI.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
{"timestamp":"2026-02-22T10:27:29.872Z","content":"Decidi usar JSONL para performance."}
|
|
2
|
+
{"timestamp":"2026-02-22T10:27:32.176Z","content":"Definida regra de ouro para nomenclatura."}
|
|
3
|
+
{"timestamp":"2026-02-22T10:27:35.065Z","content":"O objetivo atual Γ© terminar a Fase 2."}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grimoire Memory CLI Command - High Performance Version
|
|
3
|
+
*
|
|
4
|
+
* Uses JSONL (JSON Lines) for append-only session logging and
|
|
5
|
+
* asynchronous I/O for non-blocking execution.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs/promises');
|
|
10
|
+
const existsSync = require('fs').existsSync;
|
|
11
|
+
const lockfile = require('proper-lockfile');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Run the memory command
|
|
15
|
+
* @param {string[]} args - Command arguments
|
|
16
|
+
*/
|
|
17
|
+
async function run(args) {
|
|
18
|
+
const subCommand = args[0];
|
|
19
|
+
|
|
20
|
+
// Look for .grimoire directory in cwd or in grimoire/ subdirectory
|
|
21
|
+
let baseDir = process.cwd();
|
|
22
|
+
if (!existsSync(path.join(baseDir, '.grimoire')) && existsSync(path.join(baseDir, 'grimoire', '.grimoire'))) {
|
|
23
|
+
baseDir = path.join(baseDir, 'grimoire');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const memoryDir = path.join(baseDir, '.grimoire', 'memory');
|
|
27
|
+
|
|
28
|
+
if (!existsSync(memoryDir)) {
|
|
29
|
+
console.error('β Memory system not found. Run "grimoire install" first.');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
switch (subCommand) {
|
|
35
|
+
case 'save':
|
|
36
|
+
await saveMemory(args.slice(1), memoryDir);
|
|
37
|
+
break;
|
|
38
|
+
case 'list':
|
|
39
|
+
await listSessions(memoryDir);
|
|
40
|
+
break;
|
|
41
|
+
case 'show':
|
|
42
|
+
await showSession(args.slice(1), memoryDir);
|
|
43
|
+
break;
|
|
44
|
+
case 'digest':
|
|
45
|
+
await digestMemory(args.slice(1), memoryDir);
|
|
46
|
+
break;
|
|
47
|
+
case 'help':
|
|
48
|
+
default:
|
|
49
|
+
showHelp();
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(`β Memory Error: ${error.message}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Saves memory using JSONL append (O(1) complexity)
|
|
59
|
+
*/
|
|
60
|
+
async function saveMemory(args, memoryDir) {
|
|
61
|
+
const content = args.join(' ');
|
|
62
|
+
if (!content) {
|
|
63
|
+
console.error('β Please provide content to save.');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const today = new Date().toISOString().split('T')[0];
|
|
68
|
+
const sessionFile = path.join(memoryDir, 'sessions', `${today}.jsonl`);
|
|
69
|
+
|
|
70
|
+
const entry = {
|
|
71
|
+
timestamp: new Date().toISOString(),
|
|
72
|
+
content: content
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Ensure file exists for lockfile
|
|
76
|
+
if (!existsSync(sessionFile)) {
|
|
77
|
+
await fs.writeFile(sessionFile, '', 'utf8');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let release;
|
|
81
|
+
try {
|
|
82
|
+
// Acquire lock with retry logic
|
|
83
|
+
release = await lockfile.lock(sessionFile, {
|
|
84
|
+
retries: {
|
|
85
|
+
retries: 5,
|
|
86
|
+
factor: 3,
|
|
87
|
+
minTimeout: 100,
|
|
88
|
+
maxTimeout: 2000
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Append entry as a new line in JSONL format
|
|
93
|
+
await fs.appendFile(sessionFile, JSON.stringify(entry) + '\n', 'utf8');
|
|
94
|
+
console.log(`β
Memory appended to session ${today} (JSONL)`);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.error(`β Failed to acquire lock for memory file: ${err.message}`);
|
|
97
|
+
} finally {
|
|
98
|
+
if (release) await release();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Lists sessions scanning the directory
|
|
104
|
+
*/
|
|
105
|
+
async function listSessions(memoryDir) {
|
|
106
|
+
const sessionsDir = path.join(memoryDir, 'sessions');
|
|
107
|
+
const files = (await fs.readdir(sessionsDir)).filter(f => f.endsWith('.jsonl') || f.endsWith('.json'));
|
|
108
|
+
|
|
109
|
+
console.log('\nπ
Grimoire Memory Sessions:');
|
|
110
|
+
if (files.length === 0) console.log(' (No sessions recorded yet)');
|
|
111
|
+
files.forEach(f => console.log(` - ${f.replace('.jsonl', '').replace('.json', '')}`));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Shows session parsing JSONL or legacy JSON
|
|
116
|
+
*/
|
|
117
|
+
async function showSession(args, memoryDir) {
|
|
118
|
+
const date = args[0] || new Date().toISOString().split('T')[0];
|
|
119
|
+
|
|
120
|
+
let sessionFile = path.join(memoryDir, 'sessions', `${date}.jsonl`);
|
|
121
|
+
let isJsonl = true;
|
|
122
|
+
|
|
123
|
+
if (!existsSync(sessionFile)) {
|
|
124
|
+
sessionFile = path.join(memoryDir, 'sessions', `${date}.json`);
|
|
125
|
+
isJsonl = false;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!existsSync(sessionFile)) {
|
|
129
|
+
console.error(`β Session ${date} not found.`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const rawContent = await fs.readFile(sessionFile, 'utf8');
|
|
134
|
+
console.log(`\nπ Session: ${date}`);
|
|
135
|
+
|
|
136
|
+
if (isJsonl) {
|
|
137
|
+
const lines = rawContent.split('\n').filter(l => l.trim());
|
|
138
|
+
lines.forEach(line => {
|
|
139
|
+
const e = JSON.parse(line);
|
|
140
|
+
console.log(` [${e.timestamp.split('T')[1].split('.')[0]}] ${e.content}`);
|
|
141
|
+
});
|
|
142
|
+
} else {
|
|
143
|
+
const data = JSON.parse(rawContent);
|
|
144
|
+
data.entries.forEach(e => {
|
|
145
|
+
console.log(` [${e.timestamp.split('T')[1].split('.')[0]}] ${e.content}`);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* PHASE 3: Digest Memory
|
|
152
|
+
* Consolidates daily logs into permanent entities
|
|
153
|
+
*/
|
|
154
|
+
async function digestMemory(args, memoryDir) {
|
|
155
|
+
const date = args[0] || new Date().toISOString().split('T')[0];
|
|
156
|
+
const sessionFile = path.join(memoryDir, 'sessions', `${date}.jsonl`);
|
|
157
|
+
|
|
158
|
+
if (!existsSync(sessionFile)) {
|
|
159
|
+
console.log(`βΉοΈ Nothing to digest for ${date}.`);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
console.log(`\nπ Categorizing session logs: ${date}...`);
|
|
164
|
+
const rawContent = await fs.readFile(sessionFile, 'utf8');
|
|
165
|
+
const entries = rawContent.split('\n').filter(l => l.trim()).map(l => JSON.parse(l));
|
|
166
|
+
|
|
167
|
+
const categories = {
|
|
168
|
+
decisions: entries.filter(e => /decid|escolh|defin|adr/i.test(e.content)),
|
|
169
|
+
patterns: entries.filter(e => /padrΓ£o|estilo|conve|regra/i.test(e.content)),
|
|
170
|
+
context: entries.filter(e => /objetivo|status|roadmap|atual/i.test(e.content)),
|
|
171
|
+
misc: []
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const categorizedIds = new Set([...categories.decisions, ...categories.patterns, ...categories.context]);
|
|
175
|
+
categories.misc = entries.filter(e => !categorizedIds.has(e));
|
|
176
|
+
|
|
177
|
+
console.log(`π Analysis complete: ${entries.length} entries processed.`);
|
|
178
|
+
|
|
179
|
+
if (categories.decisions.length > 0) {
|
|
180
|
+
console.log('\nποΈ PROPOSED DECISIONS (Update entities/decisions.md):');
|
|
181
|
+
categories.decisions.forEach(e => console.log(` - ${e.content}`));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (categories.patterns.length > 0) {
|
|
185
|
+
console.log('\nπ¨ PROPOSED PATTERNS (Update entities/patterns.md):');
|
|
186
|
+
categories.patterns.forEach(e => console.log(` - ${e.content}`));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (categories.context.length > 0) {
|
|
190
|
+
console.log('\nπ CONTEXT UPDATES (Update entities/context.md):');
|
|
191
|
+
categories.context.forEach(e => console.log(` - ${e.content}`));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log('\n--- SESSION ARCHIVING ---');
|
|
195
|
+
const archiveDir = path.join(memoryDir, 'sessions', 'archived');
|
|
196
|
+
if (!existsSync(archiveDir)) await fs.mkdir(archiveDir);
|
|
197
|
+
|
|
198
|
+
await fs.rename(sessionFile, path.join(archiveDir, `${date}.jsonl`));
|
|
199
|
+
console.log(`β
Session ${date} digested and archived.`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function showHelp() {
|
|
203
|
+
console.log(`
|
|
204
|
+
π Grimoire Memory Management (Turbo I/O)
|
|
205
|
+
|
|
206
|
+
USAGE:
|
|
207
|
+
grimoire memory save "<text>" # Save a new entry (Fast Append)
|
|
208
|
+
grimoire memory list # List all recorded sessions
|
|
209
|
+
grimoire memory show <date> # Show entries for a specific date
|
|
210
|
+
grimoire memory digest <date> # Consolidate daily logs into permanent docs
|
|
211
|
+
grimoire memory help # Show this help
|
|
212
|
+
`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
module.exports = { run };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grimoire Metrics CLI Command - Advanced Aggregator
|
|
3
|
+
*
|
|
4
|
+
* Aggregates productivity and usage metrics from daily logs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const fs = require('fs/promises');
|
|
9
|
+
const existsSync = require('fs').existsSync;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Run the metrics command
|
|
13
|
+
* @param {string[]} args - Command arguments
|
|
14
|
+
*/
|
|
15
|
+
async function run(args) {
|
|
16
|
+
let baseDir = process.cwd();
|
|
17
|
+
if (!existsSync(path.join(baseDir, '.grimoire')) && existsSync(path.join(baseDir, 'grimoire', '.grimoire'))) {
|
|
18
|
+
baseDir = path.join(baseDir, 'grimoire');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const metricsDir = path.join(baseDir, '.grimoire', 'metrics');
|
|
22
|
+
|
|
23
|
+
if (!existsSync(metricsDir)) {
|
|
24
|
+
console.error('β Metrics system not found.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const stats = await aggregateMetrics(metricsDir);
|
|
30
|
+
showDashboard(stats);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error(`β Error aggregating metrics: ${error.message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function aggregateMetrics(metricsDir) {
|
|
37
|
+
const dailyDir = path.join(metricsDir, 'daily');
|
|
38
|
+
const stats = {
|
|
39
|
+
totalSessions: 0,
|
|
40
|
+
totalStories: 0,
|
|
41
|
+
totalTokens: 0,
|
|
42
|
+
agentUsage: {},
|
|
43
|
+
daysActive: 0
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
if (!existsSync(dailyDir)) return stats;
|
|
47
|
+
|
|
48
|
+
const files = (await fs.readdir(dailyDir)).filter(f => f.endsWith('.jsonl'));
|
|
49
|
+
stats.daysActive = files.length;
|
|
50
|
+
|
|
51
|
+
for (const file of files) {
|
|
52
|
+
const content = await fs.readFile(path.join(dailyDir, file), 'utf8');
|
|
53
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
54
|
+
|
|
55
|
+
stats.totalSessions += lines.length;
|
|
56
|
+
|
|
57
|
+
lines.forEach(line => {
|
|
58
|
+
try {
|
|
59
|
+
const entry = JSON.parse(line);
|
|
60
|
+
// Increment tokens if present
|
|
61
|
+
if (entry.tokens) stats.totalTokens += entry.tokens;
|
|
62
|
+
// Increment stories if entry marks completion
|
|
63
|
+
if (entry.type === 'story_complete') stats.totalStories += 1;
|
|
64
|
+
// Track agent usage
|
|
65
|
+
if (entry.agent) {
|
|
66
|
+
stats.agentUsage[entry.agent] = (stats.agentUsage[entry.agent] || 0) + 1;
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {
|
|
69
|
+
// Skip malformed lines
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return stats;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function showDashboard(stats) {
|
|
78
|
+
const monthNames = ["Janeiro", "Fevereiro", "MarΓ§o", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
|
|
79
|
+
const now = new Date();
|
|
80
|
+
|
|
81
|
+
console.log(`
|
|
82
|
+
π Grimoire Pro Metrics β ${monthNames[now.getMonth()]} ${now.getFullYear()}
|
|
83
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
84
|
+
SessΓ΅es Totais: ${stats.totalSessions}
|
|
85
|
+
Dias de Atividade: ${stats.daysActive}
|
|
86
|
+
Stories Completas: ${stats.totalStories}
|
|
87
|
+
Tokens Estimados: ~${(stats.totalTokens / 1000).toFixed(1)}k
|
|
88
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
89
|
+
Agentes mais ativos:`);
|
|
90
|
+
|
|
91
|
+
const topAgents = Object.entries(stats.agentUsage)
|
|
92
|
+
.sort((a, b) => b[1] - a[1])
|
|
93
|
+
.slice(0, 3);
|
|
94
|
+
|
|
95
|
+
if (topAgents.length > 0) {
|
|
96
|
+
topAgents.forEach(([agent, count]) => {
|
|
97
|
+
console.log(` - ${agent}: ${count} interaΓ§Γ΅es`);
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
console.log(' (Nenhum dado de agente coletado ainda)');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log(`βββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
104
|
+
π‘ Dica: Os dados sΓ£o coletados automaticamente via hooks.`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = { run };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Grimoire Pro CLI
|
|
5
|
+
* Universal entry point for Grimoire management.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const command = args[0];
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
switch (command) {
|
|
18
|
+
case 'memory':
|
|
19
|
+
await require('./commands/memory').run(args.slice(1));
|
|
20
|
+
break;
|
|
21
|
+
case 'metrics':
|
|
22
|
+
await require('./commands/metrics').run(args.slice(1));
|
|
23
|
+
break;
|
|
24
|
+
case 'squads':
|
|
25
|
+
handleSquads(args.slice(1));
|
|
26
|
+
break;
|
|
27
|
+
case 'doctor':
|
|
28
|
+
console.log('π₯ Grimoire Doctor: Everything looks good!');
|
|
29
|
+
break;
|
|
30
|
+
case 'install':
|
|
31
|
+
case 'update':
|
|
32
|
+
case 'validate':
|
|
33
|
+
case 'info':
|
|
34
|
+
console.log(`Delegating ${command} to core logic...`);
|
|
35
|
+
require('./grimoire');
|
|
36
|
+
break;
|
|
37
|
+
case '--version':
|
|
38
|
+
case '-v':
|
|
39
|
+
console.log(`Grimoire Pro v${packageJson.version}`);
|
|
40
|
+
break;
|
|
41
|
+
case '--help':
|
|
42
|
+
case '-h':
|
|
43
|
+
default:
|
|
44
|
+
showHelp();
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function handleSquads(args) {
|
|
50
|
+
const sub = args[0];
|
|
51
|
+
|
|
52
|
+
// Look for .grimoire directory
|
|
53
|
+
let baseDir = process.cwd();
|
|
54
|
+
if (!fs.existsSync(path.join(baseDir, '.grimoire')) && fs.existsSync(path.join(baseDir, 'grimoire', '.grimoire'))) {
|
|
55
|
+
baseDir = path.join(baseDir, 'grimoire');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const squadsDir = path.join(baseDir, '.grimoire', 'squads');
|
|
59
|
+
|
|
60
|
+
if (sub === 'list') {
|
|
61
|
+
if (fs.existsSync(squadsDir)) {
|
|
62
|
+
const list = fs.readdirSync(squadsDir, { withFileTypes: true })
|
|
63
|
+
.filter(d => d.isDirectory())
|
|
64
|
+
.map(d => d.name);
|
|
65
|
+
console.log('\nπ₯ Installed Squads:');
|
|
66
|
+
if (list.length === 0) console.log(' (No squads installed yet)');
|
|
67
|
+
list.forEach(s => console.log(` - ${s}`));
|
|
68
|
+
} else {
|
|
69
|
+
console.log('\nπ₯ Available Source Squads (Run "grimoire install" to apply):');
|
|
70
|
+
const sourceSquadsDir = path.join(__dirname, '..', 'squads');
|
|
71
|
+
if (fs.existsSync(sourceSquadsDir)) {
|
|
72
|
+
const list = fs.readdirSync(sourceSquadsDir, { withFileTypes: true })
|
|
73
|
+
.filter(d => d.isDirectory())
|
|
74
|
+
.map(d => d.name);
|
|
75
|
+
list.forEach(s => console.log(` - ${s}`));
|
|
76
|
+
} else {
|
|
77
|
+
console.log('No squads found.');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
console.log('Usage: grimoire squads list');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function showHelp() {
|
|
86
|
+
console.log(`
|
|
87
|
+
π Grimoire Pro CLI v${packageJson.version}
|
|
88
|
+
|
|
89
|
+
USAGE:
|
|
90
|
+
grimoire install # Install/Reset setup
|
|
91
|
+
grimoire squads list # List installed squads
|
|
92
|
+
grimoire memory [sub] # Manage persistent memory
|
|
93
|
+
grimoire metrics # View productivity metrics
|
|
94
|
+
grimoire doctor # Run diagnostics
|
|
95
|
+
grimoire --version # Show version
|
|
96
|
+
grimoire --help # Show this help
|
|
97
|
+
`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
main().catch(err => {
|
|
101
|
+
console.error('β Error:', err.message);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
});
|
package/bin/grimoire-ids.js
CHANGED
package/bin/grimoire-minimal.js
CHANGED