great-cto 2.85.1 → 2.85.3

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.
@@ -2,7 +2,7 @@
2
2
  "name": "great_cto",
3
3
  "id": "great_cto",
4
4
  "description": "Engineering process for solo founders and teams up to 50 engineers. Agents do architecture, code review, QA, and security. You make two decisions per feature.",
5
- "version": "2.85.1",
5
+ "version": "2.85.3",
6
6
  "author": {
7
7
  "name": "Great CTO",
8
8
  "url": "https://github.com/avelikiy/great_cto"
@@ -81,18 +81,28 @@ function readVerdicts(cwd = null) {
81
81
  }
82
82
  } // end verdictDirs loop
83
83
 
84
- // Fallback: enrich verdicts that lack cost_usd from .great_cto/cost-history.log.
85
- // Format: "<ISO-ts> <agent> <cost_usd>" per line (written by scripts/log-verdict.sh).
86
- // Match by ts (minute precision) + agent to avoid double-counting.
87
- const histPath = path.join(GREAT_CTO_DIR, 'cost-history.log');
88
- if (fs.existsSync(histPath)) {
84
+ // Fallback: enrich verdicts that lack cost_usd from cost-history.log.
85
+ // Format: "<ISO-ts> <agent> <cost_usd>" per line. Both scripts/log-verdict.sh
86
+ // and the SubagentStop measured-cost hook write it PROJECT-LOCAL
87
+ // (<cwd>/.great_cto/cost-history.log) — reading only the global ~/.great_cto
88
+ // copy (as this did before) meant the enrichment never fired for real
89
+ // projects. Read project-local first, global second. Match by ts (minute
90
+ // precision) + agent to avoid double-counting.
91
+ const histPaths = [
92
+ cwd ? path.join(cwd, '.great_cto', 'cost-history.log') : null,
93
+ path.join(GREAT_CTO_DIR, 'cost-history.log'),
94
+ ].filter(Boolean);
95
+ {
89
96
  const costByKey = new Map();
90
- const lines = fs.readFileSync(histPath, 'utf8').split('\n').filter(Boolean);
91
- for (const line of lines) {
92
- const m = line.match(/^(\S+)\s+(\S+)\s+(\d+\.?\d*)/);
93
- if (!m) continue;
94
- const key = `${m[1].slice(0, 16)}|${m[2]}`; // minute + agent
95
- costByKey.set(key, parseFloat(m[3]));
97
+ for (const histPath of histPaths) {
98
+ if (!fs.existsSync(histPath)) continue;
99
+ const lines = fs.readFileSync(histPath, 'utf8').split('\n').filter(Boolean);
100
+ for (const line of lines) {
101
+ const m = line.match(/^(\S+)\s+(\S+)\s+(\d+\.?\d*)/);
102
+ if (!m) continue;
103
+ const key = `${m[1].slice(0, 16)}|${m[2]}`; // minute + agent
104
+ if (!costByKey.has(key)) costByKey.set(key, parseFloat(m[3])); // project wins
105
+ }
96
106
  }
97
107
  for (const v of results) {
98
108
  if (v.cost_usd != null) continue;
@@ -3159,7 +3159,7 @@ function renderCost(d) {
3159
3159
  <div class="cost-cell ${overBudget ? 'warn' : (budget != null ? 'good' : '')}">
3160
3160
  <div class="lbl">Projected month</div>
3161
3161
  <div class="v">$${projected.toFixed(0)}</div>
3162
- <div class="sub">${budget != null ? (overBudget ? `over budget by $${(projected - budget).toFixed(0)}` : `${Math.round((projected/budget)*100)}% of $${budget} budget`) : 'set monthly-budget in PROJECT.md'}</div>
3162
+ <div class="sub">${budget > 0 ? (overBudget ? `over budget by $${(projected - budget).toFixed(0)}` : `${Math.round((projected/budget)*100)}% of $${budget} budget`) : 'set monthly-budget in PROJECT.md'}</div>
3163
3163
  </div>
3164
3164
  <div class="cost-cell good">
3165
3165
  <div class="lbl">vs Human team</div>
@@ -3484,6 +3484,7 @@ async function switchProject(slug) {
3484
3484
  loadMemory();
3485
3485
  refreshCost();
3486
3486
  refreshPipeline();
3487
+ refreshLogs(); // populate the Logs nav badge (was lazy — stuck at 0 until the tab was opened)
3487
3488
  refreshAgentsInstalled(); // reload agents with verdicts for the new project
3488
3489
  connectSSE();
3489
3490
  if (lbl) lbl.textContent = 'live · synced just now';
@@ -3671,6 +3672,7 @@ async function init() {
3671
3672
  loadMemory();
3672
3673
  refreshCost();
3673
3674
  refreshPipeline();
3675
+ refreshLogs(); // populate the Logs nav badge (was lazy — stuck at 0 until the tab was opened)
3674
3676
  refreshAgentsInstalled(); // preload fleet so Agents tab is instant
3675
3677
  connectSSE();
3676
3678
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "great-cto",
3
- "version": "2.85.1",
3
+ "version": "2.85.3",
4
4
  "description": "One command install for the great_cto Claude Code plugin. Auto-detects your stack, picks the right archetype, bootstraps PROJECT.md.",
5
5
  "keywords": [
6
6
  "claude-code",