tenbo-dashboard 0.10.0 → 0.10.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tenbo-dashboard",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Local-first architecture dashboard and CLI tools for .tenbo/ repos",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -56,4 +56,19 @@ describe('bin output', () => {
56
56
  { id: 'ed-001', title: 'Large Output', status: 'done' },
57
57
  ]);
58
58
  });
59
+
60
+ it('prints items help without running the query', () => {
61
+ const bin = path.resolve('bin/tenbo-dashboard.mjs');
62
+ const result = spawnSync(process.execPath, [bin, 'items', '--help'], {
63
+ cwd: dir,
64
+ encoding: 'utf8',
65
+ maxBuffer: 1024 * 1024,
66
+ });
67
+
68
+ expect(result.status).toBe(0);
69
+ expect(result.stderr).toBe('');
70
+ expect(result.stdout).toContain('Usage: tenbo-dashboard items');
71
+ expect(result.stdout).toContain('--fields <a,b>');
72
+ expect(result.stdout).not.toContain('ed-001');
73
+ });
59
74
  });
@@ -82,6 +82,26 @@ describe('items CLI', () => {
82
82
  ]);
83
83
  });
84
84
 
85
+ it('includes goal_ref in selected compact fields', () => {
86
+ writeFileSync(path.join(dir, '.tenbo/scopes/editor/roadmap.yaml'), [
87
+ 'items:',
88
+ ' - id: ed-001',
89
+ ' title: First',
90
+ ' layer: app',
91
+ ' status: next',
92
+ ' description: first item',
93
+ ' goal_ref: [g1, g2]',
94
+ '',
95
+ ].join('\n'));
96
+
97
+ const result = runItemsCli(dir, ['--fields', 'id,title,goal_ref', '--json']);
98
+
99
+ expect(result.exitCode).toBe(0);
100
+ expect(JSON.parse(result.stdout).items).toEqual([
101
+ { id: 'ed-001', title: 'First', goal_ref: ['g1', 'g2'] },
102
+ ]);
103
+ });
104
+
85
105
  it('returns compact summaries without changing full JSON by default', () => {
86
106
  const summary = runItemsCli(dir, ['--status', 'next', '--summary', '--json']);
87
107
  const full = runItemsCli(dir, ['--status', 'next', '--json']);
package/scripts/items.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { listItems, type ListItemFilters } from '../src/api/lib/roadmapStore';
2
2
  import { parseItemFields, projectItem, summarizeItem } from '../src/api/lib/itemProjection';
3
3
  import { hasFlag, readOption } from './cliArgs';
4
- import { handleCliError, isMain, misuse, repoRootFromCwd, runMain, serialize, type CliResult } from './cliResult';
4
+ import { handleCliError, isMain, misuse, ok, repoRootFromCwd, runMain, serialize, type CliResult } from './cliResult';
5
5
 
6
6
  const STATUSES = new Set(['now', 'next', 'later', 'done', 'dropped']);
7
+ const USAGE = `Usage: tenbo-dashboard items [--status <status[,status]>] [--verification <status>] [--goal <goal>] [--type <type>] [--priority <p0|p1|p2|p3>] [--layer <id>] [--fields <a,b>] [--summary] [--json]
8
+ `;
7
9
 
8
10
  function readStatusFilter(value: string | undefined): ListItemFilters['status'] {
9
11
  if (!value) return undefined;
@@ -49,7 +51,8 @@ export function runItemsCli(repoRoot: string, args: string[]): CliResult {
49
51
  if (isMain(import.meta.url)) {
50
52
  const args = process.argv.slice(2);
51
53
  if (args.includes('--help')) {
52
- runMain(fail('invalid_args', 'Usage: tenbo items [--status <status>] [--verification <status>] [--goal <goal>] [--json]', false));
54
+ runMain(ok(USAGE));
55
+ } else {
56
+ runMain(runItemsCli(repoRootFromCwd(), args));
53
57
  }
54
- runMain(runItemsCli(repoRootFromCwd(), args));
55
58
  }
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, afterEach } from 'vitest';
2
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readdirSync, utimesSync } from 'node:fs';
2
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, readdirSync, utimesSync } from 'node:fs';
3
3
  import { tmpdir } from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { spawnSync } from 'node:child_process';
@@ -27,7 +27,7 @@
27
27
  * decoration so callers can capture it via `$(...)`. Errors go to stderr
28
28
  * and the process exits non-zero.
29
29
  */
30
- import { readFileSync, existsSync, mkdirSync, readdirSync, writeFileSync, statSync, unlinkSync, openSync, closeSync, writeSync } from 'node:fs';
30
+ import { readFileSync, existsSync, mkdirSync, statSync, unlinkSync, openSync, closeSync, writeSync } from 'node:fs';
31
31
  import path from 'node:path';
32
32
  import { parse as parseYaml } from 'yaml';
33
33
  import { findRepoRoot } from '../src/api/lib/repoRoot';
@@ -41,10 +41,6 @@ interface WorkspaceScope {
41
41
  path?: string;
42
42
  }
43
43
 
44
- interface RoadmapFile {
45
- items?: Array<{ id?: string }>;
46
- }
47
-
48
44
  /** Find which roadmap.yaml files contain ids for this prefix. */
49
45
  export function resolveRoadmapPaths(repoRoot: string, prefix: string): string[] {
50
46
  const tenbo = path.join(repoRoot, '.tenbo');
@@ -10,6 +10,7 @@ export interface ItemSummaryRecord {
10
10
  layers?: string[];
11
11
  type?: Item['type'];
12
12
  priority?: Priority;
13
+ goal_ref?: Item['goal_ref'];
13
14
  verification?: VerificationStatus;
14
15
  risk_count?: number;
15
16
  done_when_count?: number;
@@ -25,6 +26,7 @@ export const ITEM_FIELD_NAMES = [
25
26
  'layers',
26
27
  'type',
27
28
  'priority',
29
+ 'goal_ref',
28
30
  'verification',
29
31
  'risk_count',
30
32
  'done_when_count',
@@ -60,6 +62,7 @@ export function summarizeItem(entry: LocatedItem): ItemSummaryRecord {
60
62
  ...(item.layers ? { layers: item.layers } : {}),
61
63
  ...(item.type ? { type: item.type } : {}),
62
64
  ...(item.priority ? { priority: item.priority } : {}),
65
+ ...(item.goal_ref ? { goal_ref: item.goal_ref } : {}),
63
66
  ...(item.verification?.status ? { verification: item.verification.status } : {}),
64
67
  ...(item.risks ? { risk_count: item.risks.length } : {}),
65
68
  ...(item.done_when ? { done_when_count: item.done_when.length } : {}),
package/tsconfig.json CHANGED
@@ -14,5 +14,5 @@
14
14
  "allowImportingTsExtensions": false,
15
15
  "noEmit": true
16
16
  },
17
- "include": ["src", "tests", "vite.config.ts"]
17
+ "include": ["src", "tests", "scripts", "vite.config.ts"]
18
18
  }