up-cc 0.6.0 → 0.8.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/README.md +6 -2
- package/agents/up-architecture-supervisor.md +9 -5
- package/agents/up-arquiteto.md +45 -0
- package/agents/up-audit-supervisor.md +13 -3
- package/agents/up-backend-specialist.md +12 -5
- package/agents/up-code-reviewer.md +6 -2
- package/agents/up-database-specialist.md +12 -5
- package/agents/up-execution-supervisor.md +19 -7
- package/agents/up-executor.md +12 -5
- package/agents/up-frontend-specialist.md +12 -5
- package/agents/up-operations-supervisor.md +7 -3
- package/agents/up-planning-supervisor.md +12 -7
- package/agents/up-product-supervisor.md +9 -4
- package/agents/up-quality-supervisor.md +11 -6
- package/agents/up-verification-supervisor.md +11 -6
- package/bin/install.js +254 -8
- package/bin/up-instrument.cjs +333 -0
- package/commands/custos.md +67 -0
- package/package.json +2 -2
- package/references/engineering-principles-compressed.md +26 -0
- package/references/governance-rules-compressed.md +31 -0
- package/references/production-requirements-compressed.md +23 -0
- package/references/rework-limits-compressed.md +22 -0
- package/workflows/build.md +63 -5
- package/workflows/governance.md +26 -4
- package/workflows/plan.md +17 -5
- package/workflows/planejar-fase.md +27 -9
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UP Instrumentation — measures token usage per UP agent
|
|
5
|
+
*
|
|
6
|
+
* Reads Claude Code session.jsonl + subagent jsonls and produces a token cost
|
|
7
|
+
* report grouped by agent. Used to identify the heaviest agents (so we know
|
|
8
|
+
* where to apply tiered context optimizations) and to give users visibility
|
|
9
|
+
* into the cost of a build.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node up-instrument.cjs report # current project, current session
|
|
13
|
+
* node up-instrument.cjs report --all-sessions # current project, all sessions
|
|
14
|
+
* node up-instrument.cjs report --json # JSON output
|
|
15
|
+
* node up-instrument.cjs watch # write .plano/INSTRUMENTATION.md continuously
|
|
16
|
+
*
|
|
17
|
+
* Opt-in via /up:configurar (instrumentation.enabled = true).
|
|
18
|
+
* Default: off.
|
|
19
|
+
*
|
|
20
|
+
* NOTE: Only works with Claude Code runtime (reads ~/.claude/projects).
|
|
21
|
+
* OpenCode and Gemini CLI use different log formats — falls back gracefully.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
const os = require('os');
|
|
27
|
+
|
|
28
|
+
const HOME = os.homedir();
|
|
29
|
+
const CLAUDE_PROJECTS = path.join(HOME, '.claude', 'projects');
|
|
30
|
+
|
|
31
|
+
// Convert /home/projects/up-cc → -home-projects-up-cc
|
|
32
|
+
function projectKey(cwd) {
|
|
33
|
+
return cwd.replace(/^\//, '').replace(/\//g, '-').replace(/^/, '-');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function listSessions(projectDir) {
|
|
37
|
+
if (!fs.existsSync(projectDir)) return [];
|
|
38
|
+
return fs
|
|
39
|
+
.readdirSync(projectDir, { withFileTypes: true })
|
|
40
|
+
.filter((d) => d.isDirectory())
|
|
41
|
+
.map((d) => path.join(projectDir, d.name));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function listJsonls(sessionDir) {
|
|
45
|
+
const files = [];
|
|
46
|
+
const walk = (dir) => {
|
|
47
|
+
if (!fs.existsSync(dir)) return;
|
|
48
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
49
|
+
const full = path.join(dir, entry.name);
|
|
50
|
+
if (entry.isDirectory()) walk(full);
|
|
51
|
+
else if (entry.name.endsWith('.jsonl')) files.push(full);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
walk(sessionDir);
|
|
55
|
+
return files;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseJsonl(file) {
|
|
59
|
+
const events = [];
|
|
60
|
+
let raw;
|
|
61
|
+
try {
|
|
62
|
+
raw = fs.readFileSync(file, 'utf8');
|
|
63
|
+
} catch {
|
|
64
|
+
return events;
|
|
65
|
+
}
|
|
66
|
+
for (const line of raw.split('\n')) {
|
|
67
|
+
if (!line.trim()) continue;
|
|
68
|
+
try {
|
|
69
|
+
events.push(JSON.parse(line));
|
|
70
|
+
} catch {
|
|
71
|
+
// skip malformed
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return events;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Build canonical list of UP agent names from agents/ directory.
|
|
78
|
+
// This gives us ground truth and avoids false matches like "up-hover" or "up-load".
|
|
79
|
+
function loadUpAgentNames() {
|
|
80
|
+
const candidates = [
|
|
81
|
+
path.join(__dirname, '..', 'agents'),
|
|
82
|
+
path.join(__dirname, '..', 'up', 'agents'),
|
|
83
|
+
path.join(HOME, '.claude', 'up', 'agents'),
|
|
84
|
+
path.join(HOME, '.claude', 'agents'),
|
|
85
|
+
];
|
|
86
|
+
const names = new Set();
|
|
87
|
+
for (const dir of candidates) {
|
|
88
|
+
if (!fs.existsSync(dir)) continue;
|
|
89
|
+
for (const f of fs.readdirSync(dir)) {
|
|
90
|
+
if (f.startsWith('up-') && f.endsWith('.md')) {
|
|
91
|
+
names.add(f.replace(/\.md$/, ''));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return names;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const KNOWN_UP_AGENTS = loadUpAgentNames();
|
|
99
|
+
|
|
100
|
+
// Extract agent name from a subagent jsonl path or first event.
|
|
101
|
+
// Subagent files live in <session>/subagents/agent-<id>.jsonl.
|
|
102
|
+
function detectAgentName(events, file) {
|
|
103
|
+
// Strategy 1: scan events for known UP agent names in content
|
|
104
|
+
for (const ev of events.slice(0, 5)) {
|
|
105
|
+
const c = ev?.message?.content;
|
|
106
|
+
let text = '';
|
|
107
|
+
if (typeof c === 'string') text = c;
|
|
108
|
+
else if (Array.isArray(c)) {
|
|
109
|
+
text = c
|
|
110
|
+
.map((item) => (typeof item === 'string' ? item : item?.text || ''))
|
|
111
|
+
.join(' ');
|
|
112
|
+
}
|
|
113
|
+
if (!text) continue;
|
|
114
|
+
|
|
115
|
+
// Match against canonical UP agent names
|
|
116
|
+
for (const name of KNOWN_UP_AGENTS) {
|
|
117
|
+
if (text.includes(name)) return name;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Match "Voce e o {something}" pattern from UP role definitions
|
|
121
|
+
const roleMatch = text.match(/Voce e o ([A-Z][a-zA-Z ]+?)( UP|\.|,|\n)/);
|
|
122
|
+
if (roleMatch) {
|
|
123
|
+
const role = roleMatch[1].trim().toLowerCase().replace(/\s+/g, '-');
|
|
124
|
+
const candidate = `up-${role}`;
|
|
125
|
+
if (KNOWN_UP_AGENTS.has(candidate)) return candidate;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Strategy 2: top-level fields
|
|
130
|
+
for (const ev of events.slice(0, 3)) {
|
|
131
|
+
if (ev?.subagent_type && ev.subagent_type.startsWith('up-')) {
|
|
132
|
+
return ev.subagent_type;
|
|
133
|
+
}
|
|
134
|
+
if (ev?.slug && ev.slug.startsWith('up-') && KNOWN_UP_AGENTS.has(ev.slug)) {
|
|
135
|
+
return ev.slug;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Strategy 3: file id fallback (grouped under "non-up" so we don't pollute UP stats)
|
|
140
|
+
const m = file.match(/agent-([a-z0-9]+)\.jsonl$/);
|
|
141
|
+
return m ? `non-up-agent` : 'unknown';
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function aggregateUsage(events) {
|
|
145
|
+
let input = 0;
|
|
146
|
+
let cacheCreation = 0;
|
|
147
|
+
let cacheRead = 0;
|
|
148
|
+
let output = 0;
|
|
149
|
+
let calls = 0;
|
|
150
|
+
for (const ev of events) {
|
|
151
|
+
const u = ev?.message?.usage || ev?.usage;
|
|
152
|
+
if (!u) continue;
|
|
153
|
+
input += u.input_tokens || 0;
|
|
154
|
+
cacheCreation += u.cache_creation_input_tokens || 0;
|
|
155
|
+
cacheRead += u.cache_read_input_tokens || 0;
|
|
156
|
+
output += u.output_tokens || 0;
|
|
157
|
+
calls += 1;
|
|
158
|
+
}
|
|
159
|
+
return { input, cacheCreation, cacheRead, output, calls };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Opus 4.6 1M pricing (rough): input $15/M, output $75/M, cache write $18.75/M, cache read $1.50/M
|
|
163
|
+
function estimateCost(usage) {
|
|
164
|
+
const PRICE = {
|
|
165
|
+
input: 15 / 1_000_000,
|
|
166
|
+
cacheCreation: 18.75 / 1_000_000,
|
|
167
|
+
cacheRead: 1.5 / 1_000_000,
|
|
168
|
+
output: 75 / 1_000_000,
|
|
169
|
+
};
|
|
170
|
+
return (
|
|
171
|
+
usage.input * PRICE.input +
|
|
172
|
+
usage.cacheCreation * PRICE.cacheCreation +
|
|
173
|
+
usage.cacheRead * PRICE.cacheRead +
|
|
174
|
+
usage.output * PRICE.output
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function formatNumber(n) {
|
|
179
|
+
if (n >= 1_000_000) return (n / 1_000_000).toFixed(2) + 'M';
|
|
180
|
+
if (n >= 1_000) return (n / 1_000).toFixed(1) + 'k';
|
|
181
|
+
return String(n);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function buildReport(opts = {}) {
|
|
185
|
+
const cwd = opts.cwd || process.cwd();
|
|
186
|
+
const projectDir = path.join(CLAUDE_PROJECTS, projectKey(cwd));
|
|
187
|
+
const sessions = listSessions(projectDir);
|
|
188
|
+
if (sessions.length === 0) {
|
|
189
|
+
return { error: 'no_sessions', message: `No Claude Code sessions found for ${cwd}. Are you running in Claude Code runtime?` };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const targetSessions = opts.allSessions ? sessions : [sessions[sessions.length - 1]];
|
|
193
|
+
const byAgent = new Map();
|
|
194
|
+
const filesScanned = [];
|
|
195
|
+
|
|
196
|
+
for (const sessionDir of targetSessions) {
|
|
197
|
+
const subagentDir = path.join(sessionDir, 'subagents');
|
|
198
|
+
const files = listJsonls(subagentDir);
|
|
199
|
+
for (const file of files) {
|
|
200
|
+
filesScanned.push(file);
|
|
201
|
+
const events = parseJsonl(file);
|
|
202
|
+
const name = detectAgentName(events, file);
|
|
203
|
+
const usage = aggregateUsage(events);
|
|
204
|
+
const prev = byAgent.get(name) || { input: 0, cacheCreation: 0, cacheRead: 0, output: 0, calls: 0, invocations: 0 };
|
|
205
|
+
prev.input += usage.input;
|
|
206
|
+
prev.cacheCreation += usage.cacheCreation;
|
|
207
|
+
prev.cacheRead += usage.cacheRead;
|
|
208
|
+
prev.output += usage.output;
|
|
209
|
+
prev.calls += usage.calls;
|
|
210
|
+
prev.invocations += 1;
|
|
211
|
+
byAgent.set(name, prev);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const rows = [];
|
|
216
|
+
let totalCost = 0;
|
|
217
|
+
let totalInput = 0;
|
|
218
|
+
let totalOutput = 0;
|
|
219
|
+
for (const [agent, u] of byAgent.entries()) {
|
|
220
|
+
const cost = estimateCost(u);
|
|
221
|
+
totalCost += cost;
|
|
222
|
+
totalInput += u.input + u.cacheCreation + u.cacheRead;
|
|
223
|
+
totalOutput += u.output;
|
|
224
|
+
rows.push({
|
|
225
|
+
agent,
|
|
226
|
+
invocations: u.invocations,
|
|
227
|
+
input: u.input + u.cacheCreation + u.cacheRead,
|
|
228
|
+
output: u.output,
|
|
229
|
+
cost,
|
|
230
|
+
avgPerInvoc: u.invocations > 0 ? (u.input + u.cacheCreation + u.cacheRead) / u.invocations : 0,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
rows.sort((a, b) => b.cost - a.cost);
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
cwd,
|
|
237
|
+
sessions: targetSessions.length,
|
|
238
|
+
files_scanned: filesScanned.length,
|
|
239
|
+
total_input_tokens: totalInput,
|
|
240
|
+
total_output_tokens: totalOutput,
|
|
241
|
+
total_cost_usd: totalCost,
|
|
242
|
+
agents: rows,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function renderMarkdown(report) {
|
|
247
|
+
if (report.error) return `# Instrumentation\n\n${report.message}\n`;
|
|
248
|
+
const lines = [];
|
|
249
|
+
lines.push('# Token Instrumentation');
|
|
250
|
+
lines.push('');
|
|
251
|
+
lines.push(`Project: \`${report.cwd}\``);
|
|
252
|
+
lines.push(`Sessions analyzed: ${report.sessions}`);
|
|
253
|
+
lines.push(`Subagent files scanned: ${report.files_scanned}`);
|
|
254
|
+
lines.push('');
|
|
255
|
+
lines.push('## Totals');
|
|
256
|
+
lines.push(`- Input tokens: **${formatNumber(report.total_input_tokens)}**`);
|
|
257
|
+
lines.push(`- Output tokens: **${formatNumber(report.total_output_tokens)}**`);
|
|
258
|
+
lines.push(`- Estimated cost (Opus 4.6 pricing): **$${report.total_cost_usd.toFixed(2)}**`);
|
|
259
|
+
lines.push('');
|
|
260
|
+
lines.push('## Top agents by cost');
|
|
261
|
+
lines.push('');
|
|
262
|
+
lines.push('| Agent | Invocations | Input | Avg/invoc | Output | Cost |');
|
|
263
|
+
lines.push('|---|---:|---:|---:|---:|---:|');
|
|
264
|
+
for (const row of report.agents.slice(0, 20)) {
|
|
265
|
+
lines.push(
|
|
266
|
+
`| ${row.agent} | ${row.invocations} | ${formatNumber(row.input)} | ${formatNumber(row.avgPerInvoc)} | ${formatNumber(row.output)} | $${row.cost.toFixed(2)} |`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
lines.push('');
|
|
270
|
+
lines.push(`> Generated by \`up-instrument\` at ${new Date().toISOString()}`);
|
|
271
|
+
lines.push('> Pricing assumes Claude Opus 4.6 1M context. Real cost may vary.');
|
|
272
|
+
return lines.join('\n') + '\n';
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function renderTable(report) {
|
|
276
|
+
if (report.error) return report.message;
|
|
277
|
+
const lines = [];
|
|
278
|
+
lines.push(`Project: ${report.cwd}`);
|
|
279
|
+
lines.push(`Sessions: ${report.sessions} Files: ${report.files_scanned}`);
|
|
280
|
+
lines.push(`Total: ${formatNumber(report.total_input_tokens)} in / ${formatNumber(report.total_output_tokens)} out / $${report.total_cost_usd.toFixed(2)}`);
|
|
281
|
+
lines.push('');
|
|
282
|
+
lines.push('Top agents:');
|
|
283
|
+
for (const row of report.agents.slice(0, 15)) {
|
|
284
|
+
const pad = (s, n) => String(s).padEnd(n);
|
|
285
|
+
lines.push(` ${pad(row.agent, 30)} ${pad(row.invocations + 'x', 6)} ${pad(formatNumber(row.input), 8)} avg ${pad(formatNumber(row.avgPerInvoc), 8)} $${row.cost.toFixed(2)}`);
|
|
286
|
+
}
|
|
287
|
+
return lines.join('\n');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// CLI
|
|
291
|
+
const args = process.argv.slice(2);
|
|
292
|
+
const cmd = args[0] || 'report';
|
|
293
|
+
const opts = {
|
|
294
|
+
allSessions: args.includes('--all-sessions'),
|
|
295
|
+
json: args.includes('--json'),
|
|
296
|
+
cwd: process.cwd(),
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
if (cmd === 'report') {
|
|
300
|
+
const report = buildReport(opts);
|
|
301
|
+
if (opts.json) {
|
|
302
|
+
console.log(JSON.stringify(report, null, 2));
|
|
303
|
+
} else {
|
|
304
|
+
console.log(renderTable(report));
|
|
305
|
+
}
|
|
306
|
+
} else if (cmd === 'write') {
|
|
307
|
+
const report = buildReport(opts);
|
|
308
|
+
const planoDir = path.join(opts.cwd, '.plano');
|
|
309
|
+
if (!fs.existsSync(planoDir)) {
|
|
310
|
+
console.error('No .plano directory found in current cwd. Run from a UP project root.');
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
const outFile = path.join(planoDir, 'INSTRUMENTATION.md');
|
|
314
|
+
fs.writeFileSync(outFile, renderMarkdown(report));
|
|
315
|
+
console.log(`Wrote ${outFile}`);
|
|
316
|
+
} else if (cmd === '--help' || cmd === 'help') {
|
|
317
|
+
console.log(`up-instrument — token usage measurement for UP agents
|
|
318
|
+
|
|
319
|
+
Commands:
|
|
320
|
+
report Print top agents by cost (default, current session)
|
|
321
|
+
report --all-sessions Same but across all sessions for current project
|
|
322
|
+
report --json JSON output
|
|
323
|
+
write Write .plano/INSTRUMENTATION.md (current session)
|
|
324
|
+
write --all-sessions Write report across all sessions
|
|
325
|
+
|
|
326
|
+
Notes:
|
|
327
|
+
- Only works with Claude Code (reads ~/.claude/projects/<key>/subagents/*.jsonl)
|
|
328
|
+
- OpenCode and Gemini CLI use different log formats and are not supported yet
|
|
329
|
+
- Pricing assumes Claude Opus 4.6 1M context — real cost may vary`);
|
|
330
|
+
} else {
|
|
331
|
+
console.error(`Unknown command: ${cmd}. Try 'help'.`);
|
|
332
|
+
process.exit(1);
|
|
333
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: up:custos
|
|
3
|
+
description: Mostra estimativa de custo em tokens dos agentes UP usados no projeto atual (Claude Code only)
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<objective>
|
|
10
|
+
Reportar custo estimado de tokens consumidos por agentes UP no projeto atual.
|
|
11
|
+
Usa `bin/up-instrument.cjs` para parsear `~/.claude/projects/<key>/subagents/*.jsonl`
|
|
12
|
+
e agregar uso por agente.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
<process>
|
|
16
|
+
|
|
17
|
+
## 1. Detectar runtime
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
if [ ! -d "$HOME/.claude/projects" ]; then
|
|
21
|
+
echo "Instrumentation requer Claude Code runtime."
|
|
22
|
+
echo "OpenCode e Gemini CLI usam formatos de log diferentes (nao suportado ainda)."
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 2. Rodar relatorio
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Default: sessao mais recente
|
|
31
|
+
node "$HOME/.claude/up/bin/up-instrument.cjs" report
|
|
32
|
+
|
|
33
|
+
# Se quiser todas as sessoes do projeto:
|
|
34
|
+
# node "$HOME/.claude/up/bin/up-instrument.cjs" report --all-sessions
|
|
35
|
+
|
|
36
|
+
# Se quiser JSON:
|
|
37
|
+
# node "$HOME/.claude/up/bin/up-instrument.cjs" report --json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 3. Salvar em .plano/INSTRUMENTATION.md (opcional)
|
|
41
|
+
|
|
42
|
+
Se a flag `--save` foi passada OU se .plano/ existe:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
if [ -d ".plano" ]; then
|
|
46
|
+
node "$HOME/.claude/up/bin/up-instrument.cjs" write
|
|
47
|
+
echo ""
|
|
48
|
+
echo "Relatorio salvo em .plano/INSTRUMENTATION.md"
|
|
49
|
+
fi
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 4. Apresentar interpretacao
|
|
53
|
+
|
|
54
|
+
Apos mostrar a tabela, comentar:
|
|
55
|
+
|
|
56
|
+
- **Top 3 agentes mais caros** — onde focar otimizacao
|
|
57
|
+
- **Total estimado** — em USD assumindo Opus 4.6 pricing
|
|
58
|
+
- **Comparacao com outras sessoes** se historico disponivel
|
|
59
|
+
|
|
60
|
+
</process>
|
|
61
|
+
|
|
62
|
+
<notes>
|
|
63
|
+
- Pricing assume Opus 4.6 1M context: input $15/M, output $75/M, cache write $18.75/M, cache read $1.50/M
|
|
64
|
+
- Custos reais podem variar conforme modelo selecionado no /model
|
|
65
|
+
- Apenas funciona em Claude Code — OpenCode e Gemini CLI nao expoe usage por subagent ainda
|
|
66
|
+
- Detecta agentes UP cruzando contra a lista canonica em `agents/up-*.md`
|
|
67
|
+
</notes>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "up-cc",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Simplified spec-driven development for Claude Code, Gemini and
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Simplified spec-driven development for Claude Code, Gemini, OpenCode and OpenAI Codex.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"up-cc": "bin/install.js"
|
|
7
7
|
},
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Engineering Principles (compressed)
|
|
2
|
+
|
|
3
|
+
> Versao compactada para injecao inline em prompts. ~400 tokens vs 2.5k da versao completa.
|
|
4
|
+
> Versao completa em `engineering-principles.md` — Read sob demanda se precisar de exemplos detalhados.
|
|
5
|
+
|
|
6
|
+
## 6 Principios
|
|
7
|
+
|
|
8
|
+
1. **Implementacao real, nao simulacao** — Zero `onClick={() => {}}`, zero placeholder, zero API que retorna `{ok: true}` estatico, zero `useState([])` sem setter, zero imports nao usados. Se nao pode implementar agora: declare explicitamente como debito tecnico.
|
|
9
|
+
|
|
10
|
+
2. **Correto, nao rapido** — Tipagem explicita (sem `any`). Validacao com lib (zod/yup). Queries parametrizadas. `===` nao `==`. `crypto.randomUUID()` nao `Math.random()`. `structuredClone` nao `Object.assign` raso.
|
|
11
|
+
|
|
12
|
+
3. **Conectado de ponta a ponta** — Componente → rota navegavel. API → frontend chama + trata response. Schema → migration rodada. Validacao → form aplica + feedback visivel. "Arquivo existe" ≠ "funciona". Usuario consegue usar no browser.
|
|
13
|
+
|
|
14
|
+
4. **Consistencia sobre criatividade** — Antes de implementar: `grep` por pattern similar no codebase. Se React Query existe, use `useQuery`. Se Button component existe, use `<Button>`. Se Tailwind, use classes. Nao invente patterns paralelos.
|
|
15
|
+
|
|
16
|
+
5. **Dados reais desde o primeiro momento** — Banco real com seed > API real > mock temporario removido > hardcoded (PROIBIDO). Se banco existe, conecte desde o primeiro componente. Mock so em testes automatizados.
|
|
17
|
+
|
|
18
|
+
6. **Cada decisao tem custo futuro** — Sem tipagem = bugs silenciosos. Sem pagination = trava com 10k items. Sem error handling = crash cego. Sem indices = queries lentas. Custo de fazer certo e linear, refatorar e exponencial.
|
|
19
|
+
|
|
20
|
+
## Aplicacao
|
|
21
|
+
|
|
22
|
+
- Antes de cada tarefa: reler mentalmente os 6
|
|
23
|
+
- Durante: checar cada decisao contra a lista
|
|
24
|
+
- Antes de commit: self-review rapido
|
|
25
|
+
- No SUMMARY: documentar violacoes como debito tecnico
|
|
26
|
+
- Para exemplos detalhados: `Read references/engineering-principles.md`
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Governance Rules (compressed)
|
|
2
|
+
|
|
3
|
+
> Versao compactada para injecao inline. ~250 tokens vs 1.9k da versao completa.
|
|
4
|
+
> Versao completa em `governance-rules.md` — Read sob demanda para hierarquia detalhada.
|
|
5
|
+
|
|
6
|
+
## Hierarquia
|
|
7
|
+
DONO → CEO → 5 Chiefs → 8 Supervisores → 36 Operacionais
|
|
8
|
+
|
|
9
|
+
## Decisoes do Supervisor (apos cada operacional)
|
|
10
|
+
- **APPROVE** — criterios atendidos, sem issues criticas, evidencia clara
|
|
11
|
+
- **REQUEST_CHANGES** — 1+ criterio falhou, feedback especifico e acionavel
|
|
12
|
+
- **ESCALATE** — fora do escopo, decisao arquitetural ou conflito → chief
|
|
13
|
+
|
|
14
|
+
## Decisoes do Chief (apos area completa)
|
|
15
|
+
- APPROVE | REQUEST_CHANGES (volta pro supervisor) | ESCALATE pro CEO
|
|
16
|
+
|
|
17
|
+
## Decisoes do CEO (antes de delivery)
|
|
18
|
+
- APPROVE_DELIVERY | ALERTA_DONO | REWORK (volta pro chief)
|
|
19
|
+
|
|
20
|
+
## Anti-patterns (NUNCA aprovar se)
|
|
21
|
+
- Trabalho nao foi de fato verificado ("parece ok")
|
|
22
|
+
- Evidencia faltando ou ambigua
|
|
23
|
+
- SUMMARY claim sem backing no codigo
|
|
24
|
+
- Rework cycle no max sem melhoria
|
|
25
|
+
- Stub/placeholder em vez de implementacao real
|
|
26
|
+
- Falta de wiring (componente criado mas nao conectado)
|
|
27
|
+
|
|
28
|
+
## Logging obrigatorio
|
|
29
|
+
Toda decisao em `.plano/governance/approvals.log | reworks.log | escalations.log`.
|
|
30
|
+
|
|
31
|
+
Para detalhes de poderes especificos por nivel: `Read references/governance-rules.md`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Production Requirements (compressed)
|
|
2
|
+
|
|
3
|
+
> Versao compactada para injecao inline. ~300 tokens vs 1.3k da versao completa.
|
|
4
|
+
> Versao completa em `production-requirements.md` — Read sob demanda para checklist completo (60+ itens).
|
|
5
|
+
|
|
6
|
+
## Categorias e contagem (cada item tem ID)
|
|
7
|
+
- **UIST** (8) — UI States: loading/error/empty/success, disabled, optimistic, confirm destrutivo
|
|
8
|
+
- **ERR** (8) — Error handling: boundaries, try/catch, sessao expirada, 404, offline, server-side validation
|
|
9
|
+
- **PERF** (9) — Performance: lazy loading, code split, debounce, pagination, cache, memo, prefetch
|
|
10
|
+
- **FORM** (8) — Forms: inline validation, mensagens especificas, autofocus, tab order, defaults, mascaras
|
|
11
|
+
- **RESP** (7) — Responsividade: 375px funcional, touch 44x44, hamburger mobile, modais fullscreen
|
|
12
|
+
- **META** (7) — Meta/SEO: title unico, og tags, favicon, manifest, canonical, robots
|
|
13
|
+
- **A11Y** (9) — Acessibilidade: alt, labels, focus visible, keyboard, aria, contraste 4.5:1, landmarks
|
|
14
|
+
- **SEC** (8) — Seguranca: rotas protegidas, CSRF, XSS, rate limit, headers, UUID, env vars, RLS
|
|
15
|
+
- **POLISH** (7) — Visual: hover, transicoes 150-300ms, escala espacamento, design tokens, dark mode
|
|
16
|
+
|
|
17
|
+
## Total: 71 requisitos de producao em 9 categorias
|
|
18
|
+
|
|
19
|
+
Quando precisar de IDs especificos ou descricao detalhada de um item:
|
|
20
|
+
`Read references/production-requirements.md` e procure pela categoria.
|
|
21
|
+
|
|
22
|
+
Arquiteto/system-designer injetam estes requisitos automaticamente no REQUIREMENTS.md.
|
|
23
|
+
Supervisores validam contra eles antes de approval.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Rework Limits (compressed)
|
|
2
|
+
|
|
3
|
+
> Versao compactada para injecao inline. ~150 tokens vs 2k da versao completa.
|
|
4
|
+
> Versao completa em `rework-limits.md` — Read sob demanda para fluxos detalhados.
|
|
5
|
+
|
|
6
|
+
## Limites por nivel
|
|
7
|
+
| Nivel | Max Ciclos | Apos limite |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| Operacional ← Supervisor | **3** | Forca approval, marca como debito tecnico |
|
|
10
|
+
| Supervisor ← Chief | **2** | Escalacao pro CEO |
|
|
11
|
+
| Chief ← CEO | **1** | CEO decide: aceitar ou alertar dono |
|
|
12
|
+
|
|
13
|
+
## Quando forcar aprovacao (apos max ciclos)
|
|
14
|
+
- Melhoria entre ciclos < 10% (diminishing returns)
|
|
15
|
+
- Issue nao pode ser resolvida sem info externa
|
|
16
|
+
- Acao: registrar em `governance/technical-debt.log`, marcar item como `completed_with_debt`
|
|
17
|
+
|
|
18
|
+
## Rework rate saudavel: 15-30%
|
|
19
|
+
- < 5% = supervisor mal calibrado, aprovando sem criterio
|
|
20
|
+
- > 40% = prompt vago ou criterios muito rigidos
|
|
21
|
+
|
|
22
|
+
Para fluxos completos por ciclo: `Read references/rework-limits.md`
|
package/workflows/build.md
CHANGED
|
@@ -181,12 +181,47 @@ Agent(
|
|
|
181
181
|
prompt=f"""
|
|
182
182
|
Executar Plano da Fase {phase_number}.
|
|
183
183
|
|
|
184
|
+
<engineering_principles_compressed>
|
|
185
|
+
1. Implementacao real, nao simulacao (zero placeholder, zero stub)
|
|
186
|
+
2. Correto, nao rapido (sem `any`, validacao com lib, queries parametrizadas)
|
|
187
|
+
3. Conectado ponta a ponta (componente → API → DB com dados fluindo)
|
|
188
|
+
4. Consistencia (grep por pattern existente antes de inventar)
|
|
189
|
+
5. Dados reais desde o primeiro momento (sem hardcode)
|
|
190
|
+
6. Cada decisao tem custo futuro (escolher solucao escalavel)
|
|
191
|
+
|
|
192
|
+
Em duvida entre rapido e correto: sempre o correto.
|
|
193
|
+
Sob demanda: Read references/engineering-principles.md para exemplos.
|
|
194
|
+
</engineering_principles_compressed>
|
|
195
|
+
|
|
196
|
+
<production_requirements_compressed>
|
|
197
|
+
Categorias a respeitar (71 requisitos no total):
|
|
198
|
+
- UIST (UI States): loading/error/empty/success em TODA operacao async
|
|
199
|
+
- ERR (Error handling): boundaries, try/catch, sessao expirada, 404
|
|
200
|
+
- PERF: lazy loading, code split, debounce, pagination > 20 items, cache
|
|
201
|
+
- FORM: validacao inline, mensagens especificas, autofocus, mascaras
|
|
202
|
+
- RESP: 375px funcional, touch 44x44, hamburger mobile
|
|
203
|
+
- A11Y: alt, labels, focus visible, keyboard, contraste 4.5:1
|
|
204
|
+
- SEC: rotas protegidas, CSRF, XSS, rate limit, env vars, RLS
|
|
205
|
+
- POLISH: hover, transicoes 150-300ms, design tokens
|
|
206
|
+
|
|
207
|
+
Sob demanda: Read references/production-requirements.md para IDs especificos.
|
|
208
|
+
</production_requirements_compressed>
|
|
209
|
+
|
|
184
210
|
<files_to_read>
|
|
211
|
+
TIER 1 — Sempre:
|
|
185
212
|
- {PLAN}
|
|
186
|
-
- .plano/
|
|
187
|
-
- .
|
|
188
|
-
|
|
189
|
-
|
|
213
|
+
- .plano/STATE.md
|
|
214
|
+
- ./CLAUDE.md (se existir)
|
|
215
|
+
|
|
216
|
+
TIER 2 — Se a slice da fase existe (v0.7.0+):
|
|
217
|
+
- .plano/fases/{phase_number}/PHASE.md (objetivo da fase)
|
|
218
|
+
- .plano/fases/{phase_number}/REQUIREMENTS-SLICE.md (REQs APENAS desta fase)
|
|
219
|
+
- .plano/DESIGN-TOKENS.md (se for frontend e existir)
|
|
220
|
+
|
|
221
|
+
TIER 3 — Sob demanda apenas:
|
|
222
|
+
- .plano/PROJECT.md (so se precisar visao geral)
|
|
223
|
+
- .plano/SYSTEM-DESIGN.md (so se decisao de arquitetura aparecer)
|
|
224
|
+
- .plano/REQUIREMENTS.md (so se a slice nao tiver info suficiente)
|
|
190
225
|
</files_to_read>
|
|
191
226
|
|
|
192
227
|
Implementar todas as tarefas. Commitar atomicamente.
|
|
@@ -203,10 +238,33 @@ Agent(
|
|
|
203
238
|
prompt=f"""
|
|
204
239
|
Revisar execucao da Fase {phase_number}.
|
|
205
240
|
|
|
241
|
+
<governance_compressed>
|
|
242
|
+
DECISOES: APPROVE | REQUEST_CHANGES | REQUEST_REPLAN | ESCALATE
|
|
243
|
+
REWORK: max 3 ciclos antes de forcar approval com debito
|
|
244
|
+
NUNCA APROVAR: trabalho nao verificado, evidencia ambigua, claim sem backing,
|
|
245
|
+
stub/placeholder, falta de wiring
|
|
246
|
+
</governance_compressed>
|
|
247
|
+
|
|
248
|
+
<engineering_principles_compressed>
|
|
249
|
+
1. Implementacao real (zero placeholder)
|
|
250
|
+
2. Correto, nao rapido
|
|
251
|
+
3. Conectado ponta a ponta
|
|
252
|
+
4. Consistencia (seguir patterns existentes)
|
|
253
|
+
5. Dados reais
|
|
254
|
+
6. Custo futuro
|
|
255
|
+
</engineering_principles_compressed>
|
|
256
|
+
|
|
206
257
|
<files_to_read>
|
|
207
258
|
- {PLAN}
|
|
208
259
|
- {PHASE_DIR}/*-SUMMARY.md
|
|
209
|
-
- git diff
|
|
260
|
+
- git diff (use Bash)
|
|
261
|
+
- .plano/fases/{phase_number}/REQUIREMENTS-SLICE.md (se existir)
|
|
262
|
+
|
|
263
|
+
Sob demanda apenas:
|
|
264
|
+
- $HOME/.claude/up/references/engineering-principles.md (exemplos)
|
|
265
|
+
- $HOME/.claude/up/references/governance-rules.md (hierarquia)
|
|
266
|
+
- $HOME/.claude/up/references/rework-limits.md (fluxos)
|
|
267
|
+
- $HOME/.claude/up/references/production-requirements.md (IDs especificos)
|
|
210
268
|
</files_to_read>
|
|
211
269
|
|
|
212
270
|
Decisao: APPROVE | REQUEST_CHANGES | REQUEST_REPLAN | ESCALATE
|
package/workflows/governance.md
CHANGED
|
@@ -32,17 +32,39 @@ Spawnar o supervisor:
|
|
|
32
32
|
```python
|
|
33
33
|
Agent(
|
|
34
34
|
subagent_type="up-{supervisor_name}",
|
|
35
|
-
model="opus",
|
|
36
35
|
prompt="""
|
|
37
36
|
Revisar output de {operacional_name} para {context}.
|
|
38
37
|
|
|
38
|
+
<governance_compressed>
|
|
39
|
+
DECISOES:
|
|
40
|
+
- APPROVE — criterios atendidos, sem issues criticas, evidencia clara
|
|
41
|
+
- REQUEST_CHANGES — 1+ criterio falhou, feedback especifico e acionavel
|
|
42
|
+
- ESCALATE — fora do escopo, decisao arquitetural ou conflito → chief
|
|
43
|
+
|
|
44
|
+
REWORK LIMITS:
|
|
45
|
+
- Operacional ← Supervisor: max 3 ciclos, depois forca approval com debito tecnico
|
|
46
|
+
- Supervisor ← Chief: max 2 ciclos, depois escala pro CEO
|
|
47
|
+
|
|
48
|
+
NUNCA APROVAR SE:
|
|
49
|
+
- Trabalho nao foi de fato verificado ("parece ok")
|
|
50
|
+
- Evidencia faltando ou ambigua
|
|
51
|
+
- SUMMARY claim sem backing no codigo
|
|
52
|
+
- Stub/placeholder em vez de implementacao real
|
|
53
|
+
- Falta de wiring (componente criado mas nao conectado)
|
|
54
|
+
|
|
55
|
+
LOG OBRIGATORIO: .plano/governance/approvals.log
|
|
56
|
+
</governance_compressed>
|
|
57
|
+
|
|
39
58
|
<files_to_read>
|
|
40
|
-
- $HOME/.claude/up/references/governance-rules.md
|
|
41
|
-
- $HOME/.claude/up/references/rework-limits.md
|
|
42
59
|
- [arquivos do output do operacional]
|
|
43
|
-
- [arquivos de contexto]
|
|
60
|
+
- [arquivos de contexto da fase — preferir slices em .plano/fases/{N}/]
|
|
44
61
|
</files_to_read>
|
|
45
62
|
|
|
63
|
+
Versoes COMPLETAS (so se decisao precisa de detalhe):
|
|
64
|
+
- Read $HOME/.claude/up/references/governance-rules.md
|
|
65
|
+
- Read $HOME/.claude/up/references/rework-limits.md
|
|
66
|
+
- Read $HOME/.claude/up/references/engineering-principles.md
|
|
67
|
+
|
|
46
68
|
Avaliar contra criterios objetivos.
|
|
47
69
|
Retornar: APPROVE | REQUEST_CHANGES | ESCALATE
|
|
48
70
|
"""
|
package/workflows/plan.md
CHANGED
|
@@ -155,12 +155,24 @@ Agent(
|
|
|
155
155
|
Sonnet-ready: SEMPRE (default v0.6.0+)
|
|
156
156
|
|
|
157
157
|
<files_to_read>
|
|
158
|
+
TIER 1 — Sempre:
|
|
158
159
|
- .plano/STATE.md
|
|
159
|
-
- .plano/ROADMAP.
|
|
160
|
-
- .plano/REQUIREMENTS.md
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
- .plano/codebase
|
|
160
|
+
- .plano/fases/{phase_number}/PHASE.md (slice do ROADMAP — v0.7.0+)
|
|
161
|
+
- .plano/fases/{phase_number}/REQUIREMENTS-SLICE.md (REQs APENAS desta fase — v0.7.0+)
|
|
162
|
+
|
|
163
|
+
TIER 2 — Se brownfield apenas:
|
|
164
|
+
- .plano/codebase/CONVENTIONS.md
|
|
165
|
+
- .plano/codebase/CONCERNS.md
|
|
166
|
+
- .plano/codebase/ARCHITECTURE.md
|
|
167
|
+
|
|
168
|
+
TIER 3 — Sob demanda apenas:
|
|
169
|
+
- .plano/SYSTEM-DESIGN.md (so se decisao arquitetural especifica)
|
|
170
|
+
- .plano/PROJECT.md (so se precisar visao geral)
|
|
171
|
+
- .plano/ROADMAP.md (so se precisar entender fases adjacentes)
|
|
172
|
+
- .plano/REQUIREMENTS.md (so se a slice nao tiver info suficiente)
|
|
173
|
+
|
|
174
|
+
FALLBACK: Se as slices nao existem (projeto pre-v0.7.0), carregar
|
|
175
|
+
.plano/ROADMAP.md e .plano/REQUIREMENTS.md completos.
|
|
164
176
|
</files_to_read>
|
|
165
177
|
|
|
166
178
|
REQs da fase: {phase_req_ids}
|