@cluesmith/codev 1.4.0 → 1.4.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.
package/bin/af.js CHANGED
File without changes
package/bin/codev.js CHANGED
File without changes
package/bin/consult.js CHANGED
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cluesmith/codev",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Codev CLI - AI-assisted software development framework",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1157,56 +1157,7 @@
1157
1157
  display: none;
1158
1158
  }
1159
1159
 
1160
- /* Files Tab Styles (Spec 0055) */
1161
- .files-container {
1162
- flex: 1;
1163
- overflow-y: auto;
1164
- display: flex;
1165
- flex-direction: column;
1166
- }
1167
-
1168
- .files-header {
1169
- display: flex;
1170
- justify-content: space-between;
1171
- align-items: center;
1172
- padding: 8px 12px;
1173
- background: var(--bg-secondary);
1174
- border-bottom: 1px solid var(--border);
1175
- }
1176
-
1177
- .files-header-title {
1178
- font-size: 12px;
1179
- color: var(--text-muted);
1180
- text-transform: uppercase;
1181
- letter-spacing: 0.5px;
1182
- }
1183
-
1184
- .files-header-actions {
1185
- display: flex;
1186
- gap: 4px;
1187
- }
1188
-
1189
- .files-header-actions button {
1190
- padding: 4px 8px;
1191
- border-radius: 4px;
1192
- border: 1px solid var(--border);
1193
- background: var(--bg-tertiary);
1194
- color: var(--text-secondary);
1195
- cursor: pointer;
1196
- font-size: 11px;
1197
- }
1198
-
1199
- .files-header-actions button:hover {
1200
- background: var(--tab-hover);
1201
- color: var(--text-primary);
1202
- }
1203
-
1204
- .files-tree {
1205
- flex: 1;
1206
- overflow-y: auto;
1207
- padding: 8px 0;
1208
- }
1209
-
1160
+ /* Tree Styles (used by dashboard file browser) */
1210
1161
  .tree-item {
1211
1162
  display: flex;
1212
1163
  align-items: center;
@@ -1270,25 +1221,6 @@
1270
1221
  display: none;
1271
1222
  }
1272
1223
 
1273
- .files-loading {
1274
- display: flex;
1275
- align-items: center;
1276
- justify-content: center;
1277
- padding: 24px;
1278
- color: var(--text-muted);
1279
- font-size: 13px;
1280
- }
1281
-
1282
- .files-error {
1283
- padding: 16px;
1284
- margin: 8px;
1285
- background: rgba(239, 68, 68, 0.1);
1286
- border: 1px solid var(--status-error);
1287
- border-radius: 6px;
1288
- color: var(--text-secondary);
1289
- font-size: 13px;
1290
- }
1291
-
1292
1224
  /* Dashboard Tab Styles (Spec 0057) */
1293
1225
  .dashboard-container {
1294
1226
  flex: 1;
@@ -1298,8 +1230,7 @@
1298
1230
  }
1299
1231
 
1300
1232
  .dashboard-header {
1301
- display: grid;
1302
- grid-template-columns: 1fr 1fr;
1233
+ display: flex;
1303
1234
  gap: 16px;
1304
1235
  padding: 16px;
1305
1236
  flex-shrink: 0;
@@ -1307,10 +1238,118 @@
1307
1238
 
1308
1239
  @media (max-width: 900px) {
1309
1240
  .dashboard-header {
1310
- grid-template-columns: 1fr;
1241
+ flex-direction: column;
1311
1242
  }
1312
1243
  }
1313
1244
 
1245
+ /* Collapsible section styles */
1246
+ .dashboard-section {
1247
+ background: var(--bg-secondary);
1248
+ border: 1px solid var(--border);
1249
+ border-radius: 8px;
1250
+ overflow: hidden;
1251
+ display: flex;
1252
+ flex-direction: column;
1253
+ }
1254
+
1255
+ .dashboard-section.section-tabs,
1256
+ .dashboard-section.section-files {
1257
+ flex: 1;
1258
+ max-height: 280px;
1259
+ }
1260
+
1261
+ .dashboard-section.section-projects {
1262
+ flex: 0 0 auto;
1263
+ margin: 0 16px 16px 16px;
1264
+ max-height: 50%;
1265
+ overflow-y: auto;
1266
+ }
1267
+
1268
+ .dashboard-section.section-projects .dashboard-section-content {
1269
+ flex: 0 0 auto;
1270
+ }
1271
+
1272
+ /* Tabs/Files expand to fill remaining space above Projects */
1273
+ .dashboard-header {
1274
+ flex: 1;
1275
+ min-height: 0;
1276
+ }
1277
+
1278
+ .dashboard-section.section-tabs,
1279
+ .dashboard-section.section-files {
1280
+ max-height: none;
1281
+ }
1282
+
1283
+ .dashboard-section-header {
1284
+ display: flex;
1285
+ justify-content: space-between;
1286
+ align-items: center;
1287
+ padding: 8px 12px;
1288
+ cursor: pointer;
1289
+ user-select: none;
1290
+ flex-shrink: 0;
1291
+ border-bottom: 1px solid var(--border);
1292
+ }
1293
+
1294
+ .dashboard-section-header:hover {
1295
+ background: var(--bg-tertiary);
1296
+ }
1297
+
1298
+ .dashboard-section-header h3 {
1299
+ font-size: 12px;
1300
+ text-transform: uppercase;
1301
+ color: var(--text-muted);
1302
+ letter-spacing: 0.5px;
1303
+ margin: 0;
1304
+ display: flex;
1305
+ align-items: center;
1306
+ gap: 6px;
1307
+ }
1308
+
1309
+ .dashboard-section-header .collapse-icon {
1310
+ font-size: 10px;
1311
+ transition: transform 0.2s;
1312
+ }
1313
+
1314
+ .dashboard-section.collapsed .collapse-icon {
1315
+ transform: rotate(-90deg);
1316
+ }
1317
+
1318
+ .dashboard-section.collapsed .dashboard-section-header {
1319
+ border-bottom: none;
1320
+ }
1321
+
1322
+ .dashboard-section-header .header-actions {
1323
+ display: flex;
1324
+ gap: 4px;
1325
+ }
1326
+
1327
+ .dashboard-section-header .header-actions button {
1328
+ padding: 4px 8px;
1329
+ border-radius: 4px;
1330
+ border: 1px solid var(--border);
1331
+ background: var(--bg-tertiary);
1332
+ color: var(--text-secondary);
1333
+ cursor: pointer;
1334
+ font-size: 11px;
1335
+ }
1336
+
1337
+ .dashboard-section-header .header-actions button:hover {
1338
+ background: var(--tab-hover);
1339
+ color: var(--text-primary);
1340
+ }
1341
+
1342
+ .dashboard-section-content {
1343
+ flex: 1;
1344
+ overflow-y: auto;
1345
+ padding: 8px 12px;
1346
+ }
1347
+
1348
+ .dashboard-section.collapsed .dashboard-section-content {
1349
+ display: none;
1350
+ }
1351
+
1352
+ /* Legacy support */
1314
1353
  .dashboard-column {
1315
1354
  background: var(--bg-secondary);
1316
1355
  border: 1px solid var(--border);
@@ -1444,12 +1483,6 @@
1444
1483
  text-align: center;
1445
1484
  }
1446
1485
 
1447
- .dashboard-projects {
1448
- flex: 1;
1449
- overflow-y: auto;
1450
- padding: 0 16px 16px 16px;
1451
- }
1452
-
1453
1486
  /* Status indicators in dashboard tab list */
1454
1487
  .dashboard-status-indicator {
1455
1488
  width: 8px;
@@ -1588,6 +1621,30 @@
1588
1621
  let pendingCloseTabId = null;
1589
1622
  let contextMenuTabId = null;
1590
1623
 
1624
+ // Collapsible section state (persisted to localStorage)
1625
+ const SECTION_STATE_KEY = 'codev-dashboard-sections';
1626
+ let sectionState = loadSectionState();
1627
+
1628
+ function loadSectionState() {
1629
+ try {
1630
+ const saved = localStorage.getItem(SECTION_STATE_KEY);
1631
+ if (saved) return JSON.parse(saved);
1632
+ } catch (e) { /* ignore */ }
1633
+ return { tabs: true, files: true, projects: true };
1634
+ }
1635
+
1636
+ function saveSectionState() {
1637
+ try {
1638
+ localStorage.setItem(SECTION_STATE_KEY, JSON.stringify(sectionState));
1639
+ } catch (e) { /* ignore */ }
1640
+ }
1641
+
1642
+ function toggleSection(section) {
1643
+ sectionState[section] = !sectionState[section];
1644
+ saveSectionState();
1645
+ renderDashboardTabContent();
1646
+ }
1647
+
1591
1648
  // Initialize
1592
1649
  function init() {
1593
1650
  buildTabsFromState();
@@ -1716,14 +1773,6 @@
1716
1773
  closeable: false
1717
1774
  });
1718
1775
 
1719
- // Files tab is second and uncloseable (Spec 0055)
1720
- tabs.push({
1721
- id: 'files',
1722
- type: 'files',
1723
- name: 'Files',
1724
- closeable: false
1725
- });
1726
-
1727
1776
  // Add file tabs from annotations
1728
1777
  for (const annotation of state.annotations || []) {
1729
1778
  tabs.push({
@@ -1855,7 +1904,7 @@
1855
1904
  // Get tab icon
1856
1905
  function getTabIcon(type) {
1857
1906
  switch (type) {
1858
- case 'dashboard': return '📋';
1907
+ case 'dashboard': return '🏠';
1859
1908
  case 'files': return '📁';
1860
1909
  case 'file': return '📄';
1861
1910
  case 'builder': return '🔨';
@@ -1964,16 +2013,6 @@
1964
2013
  return;
1965
2014
  }
1966
2015
 
1967
- // Handle files tab specially (no iframe, inline content)
1968
- if (tab.type === 'files') {
1969
- if (currentTabType !== 'files') {
1970
- currentTabType = 'files';
1971
- currentTabPort = null;
1972
- renderFilesTab();
1973
- }
1974
- return;
1975
- }
1976
-
1977
2016
  // For other tabs, only update iframe if port changed (avoid flashing on poll)
1978
2017
  if (currentTabPort !== tab.port || currentTabType !== tab.type) {
1979
2018
  currentTabPort = tab.port;
@@ -3179,53 +3218,6 @@
3179
3218
  }
3180
3219
  }
3181
3220
 
3182
- // Render the files tab (entry point)
3183
- // Only fetches on first load; use refreshFilesTree() to force reload
3184
- async function renderFilesTab() {
3185
- const content = document.getElementById('tab-content');
3186
-
3187
- // If already loaded, just render cached data (no network request)
3188
- if (filesTreeLoaded) {
3189
- renderFilesTabContent();
3190
- return;
3191
- }
3192
-
3193
- // First load - show loading state and fetch
3194
- content.innerHTML = '<div class="files-loading">Loading files...</div>';
3195
- await loadFilesTree();
3196
- renderFilesTabContent();
3197
- }
3198
-
3199
- // Render the files tab content (internal - called after data is loaded)
3200
- function renderFilesTabContent() {
3201
- const content = document.getElementById('tab-content');
3202
-
3203
- if (filesTreeError) {
3204
- content.innerHTML = `
3205
- <div class="files-container">
3206
- <div class="files-error">${escapeHtml(filesTreeError)}</div>
3207
- </div>
3208
- `;
3209
- return;
3210
- }
3211
-
3212
- content.innerHTML = `
3213
- <div class="files-container">
3214
- <div class="files-header">
3215
- <span class="files-header-title">Explorer</span>
3216
- <div class="files-header-actions">
3217
- <button onclick="collapseAllFolders()" title="Collapse All">⊟</button>
3218
- <button onclick="expandAllFolders()" title="Expand All">⊞</button>
3219
- <button onclick="refreshFilesTree()" title="Refresh">↻</button>
3220
- </div>
3221
- </div>
3222
- <div class="files-tree" id="files-tree">
3223
- ${renderTreeNodes(filesTreeData, 0)}
3224
- </div>
3225
- </div>
3226
- `;
3227
- }
3228
-
3229
3221
  // Escape a string for use inside a JavaScript string literal in onclick handlers
3230
3222
  // This handles quotes, backslashes, and other special characters
3231
3223
  function escapeJsString(str) {
@@ -3316,8 +3308,6 @@
3316
3308
  if (filesListEl) {
3317
3309
  filesListEl.innerHTML = renderDashboardFilesBrowser();
3318
3310
  }
3319
- } else if (activeTabId === 'files') {
3320
- renderFilesTabContent();
3321
3311
  }
3322
3312
  }
3323
3313
 
@@ -3394,10 +3384,9 @@
3394
3384
  function renderInfoHeader() {
3395
3385
  return `
3396
3386
  <div class="projects-info">
3397
- <h1 style="font-size: 20px; margin-bottom: 12px; color: var(--text-primary);">Codev: Project View</h1>
3398
- <p>This shows the state of all projects. Our goal is to move each project through all the stages until it reaches INTGR'D (integrated). Hover over column headers to learn about each stage.</p>
3399
- <p>To add projects, update status, or approve stages, use the <strong>Architect</strong> terminal on the left.</p>
3400
- <p>Docs: <a href="#" onclick="openProjectFile('codev/resources/cheatsheet.md'); return false;">Cheatsheet</a> · <a href="#" onclick="openProjectFile('codev/docs/lifecycle.md'); return false;">Lifecycle</a> · <a href="#" onclick="openProjectFile('codev/docs/commands/overview.md'); return false;">CLI Reference</a> · <a href="#" onclick="openProjectFile('codev/protocols/spider/protocol.md'); return false;">SPIDER Protocol</a> · <a href="https://github.com/cluesmith/codev#readme" target="_blank">README</a></p>
3387
+ <h1 style="font-size: 20px; margin-bottom: 12px; color: var(--text-primary);">Agent Farm Dashboard</h1>
3388
+ <p>Coordinate AI builders working on your codebase. The left panel shows the Architect terminal tell it what you want to build. <strong>Tabs</strong> shows open terminals (Architect, Builders, utility shells). <strong>Files</strong> lets you browse and open project files. <strong>Projects</strong> tracks work as it moves from conception to integration.</p>
3389
+ <p>Docs: <a href="#" onclick="openProjectFile('codev/resources/cheatsheet.md'); return false;">Cheatsheet</a> · <a href="#" onclick="openProjectFile('codev/resources/lifecycle.md'); return false;">Lifecycle</a> · <a href="#" onclick="openProjectFile('codev/resources/commands/overview.md'); return false;">CLI Reference</a> · <a href="#" onclick="openProjectFile('codev/protocols/spider/protocol.md'); return false;">SPIDER Protocol</a> · <a href="https://github.com/cluesmith/codev#readme" target="_blank">README</a> · <a href="https://discord.gg/mJ92DhDa6n" target="_blank">Discord</a></p>
3401
3390
  </div>
3402
3391
  `;
3403
3392
  }
@@ -3408,36 +3397,43 @@
3408
3397
 
3409
3398
  content.innerHTML = `
3410
3399
  <div class="dashboard-container">
3400
+ ${renderInfoHeader()}
3411
3401
  <div class="dashboard-header">
3412
- <!-- Left Column: Tabs -->
3413
- <div class="dashboard-column">
3414
- <div class="dashboard-column-header">
3415
- <h3>Tabs</h3>
3402
+ <!-- Tabs Section -->
3403
+ <div class="dashboard-section section-tabs ${sectionState.tabs ? '' : 'collapsed'}">
3404
+ <div class="dashboard-section-header" onclick="toggleSection('tabs')">
3405
+ <h3><span class="collapse-icon">▼</span> Tabs</h3>
3416
3406
  </div>
3417
- <div class="dashboard-tabs-list" id="dashboard-tabs-list">
3418
- ${renderDashboardTabsList()}
3419
- </div>
3420
- <div class="dashboard-actions">
3421
- <button class="btn-action" onclick="createNewShell()" title="New utility shell">+ New Shell</button>
3422
- <button class="btn-action" onclick="createNewWorktreeShell()" title="New worktree shell">+ New Worktree</button>
3407
+ <div class="dashboard-section-content">
3408
+ <div class="dashboard-tabs-list" id="dashboard-tabs-list">
3409
+ ${renderDashboardTabsList()}
3410
+ </div>
3423
3411
  </div>
3424
3412
  </div>
3425
- <!-- Right Column: Files -->
3426
- <div class="dashboard-column">
3427
- <div class="dashboard-column-header">
3428
- <h3>Files</h3>
3429
- <div class="header-actions">
3413
+ <!-- Files Section -->
3414
+ <div class="dashboard-section section-files ${sectionState.files ? '' : 'collapsed'}">
3415
+ <div class="dashboard-section-header" onclick="toggleSection('files')">
3416
+ <h3><span class="collapse-icon">▼</span> Files</h3>
3417
+ <div class="header-actions" onclick="event.stopPropagation()">
3430
3418
  <button onclick="collapseAllFolders()" title="Collapse All">⊟</button>
3431
3419
  <button onclick="expandAllFolders()" title="Expand All">⊞</button>
3432
3420
  </div>
3433
3421
  </div>
3434
- <div class="dashboard-files-list" id="dashboard-files-list">
3435
- ${renderDashboardFilesBrowser()}
3422
+ <div class="dashboard-section-content">
3423
+ <div class="dashboard-files-list" id="dashboard-files-list">
3424
+ ${renderDashboardFilesBrowser()}
3425
+ </div>
3436
3426
  </div>
3437
3427
  </div>
3438
3428
  </div>
3439
- <div class="dashboard-projects" id="dashboard-projects">
3440
- ${renderDashboardProjectsSection()}
3429
+ <!-- Projects Section -->
3430
+ <div class="dashboard-section section-projects ${sectionState.projects ? '' : 'collapsed'}">
3431
+ <div class="dashboard-section-header" onclick="toggleSection('projects')">
3432
+ <h3><span class="collapse-icon">▼</span> Projects</h3>
3433
+ </div>
3434
+ <div class="dashboard-section-content" id="dashboard-projects">
3435
+ ${renderDashboardProjectsSection()}
3436
+ </div>
3441
3437
  </div>
3442
3438
  </div>
3443
3439
  `;
@@ -3516,9 +3512,8 @@
3516
3512
  `;
3517
3513
  }
3518
3514
 
3519
- // Render the existing project view (unchanged)
3515
+ // Render the existing project view
3520
3516
  return `
3521
- ${renderInfoHeader()}
3522
3517
  ${renderKanbanGrid(projectsData)}
3523
3518
  ${renderTerminalProjects(projectsData)}
3524
3519
  `;
@@ -13,11 +13,14 @@
13
13
  </script>
14
14
  <style>
15
15
  * { box-sizing: border-box; margin: 0; padding: 0; }
16
- body {
16
+ html, body {
17
17
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
18
18
  background: #1a1a1a;
19
19
  color: #fff;
20
- min-height: 100vh;
20
+ height: 100%;
21
+ }
22
+ body.preview-active {
23
+ overflow: hidden;
21
24
  }
22
25
  .header {
23
26
  padding: 15px 20px;
@@ -785,12 +788,14 @@
785
788
  renderPreview();
786
789
  viewMode.style.display = 'none';
787
790
  previewContainer.style.display = 'block';
791
+ document.body.classList.add('preview-active');
788
792
  toggleIcon.textContent = '📝';
789
793
  toggleText.textContent = 'Annotate';
790
794
  } else {
791
795
  // Switch back to annotated view
792
796
  viewMode.style.display = 'grid';
793
797
  previewContainer.style.display = 'none';
798
+ document.body.classList.remove('preview-active');
794
799
  toggleIcon.textContent = '👁';
795
800
  toggleText.textContent = 'Preview';
796
801
  }