tenbo-dashboard 0.10.3 → 0.13.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 -0
- package/bin/tenbo-dashboard.mjs +36 -2
- package/package.json +7 -4
- package/scripts/cliArgs.ts +15 -2
- package/scripts/code-map.ts +45 -0
- package/scripts/commit-context.ts +33 -0
- package/scripts/context.ts +32 -3
- package/scripts/hook.ts +585 -17
- package/scripts/hub.ts +356 -0
- package/scripts/impact.ts +25 -0
- package/scripts/index.ts +41 -0
- package/scripts/item.ts +154 -23
- package/scripts/itemCommandRegistry.mjs +9 -0
- package/scripts/reconcile.ts +99 -0
- package/scripts/reminder.ts +24 -0
- package/scripts/sync.ts +66 -5
- package/src/api/lib/codeMapGenerator.ts +544 -0
- package/src/api/lib/commitContext.ts +156 -0
- package/src/api/lib/contextResolver.ts +809 -16
- package/src/api/lib/doneWhenChecks.ts +274 -0
- package/src/api/lib/doneWhenShape.ts +21 -0
- package/src/api/lib/health/collectAll.ts +26 -54
- package/src/api/lib/health/coupling.ts +3 -0
- package/src/api/lib/health/deadCode.ts +1 -0
- package/src/api/lib/health/importGraph.ts +3 -65
- package/src/api/lib/health/structuralGraph.ts +87 -0
- package/src/api/lib/health/types.ts +7 -2
- package/src/api/lib/hub/autostart.ts +95 -0
- package/src/api/lib/hub/client.ts +57 -0
- package/src/api/lib/hub/discover.ts +74 -0
- package/src/api/lib/hub/hubRepoRoot.ts +54 -0
- package/src/api/lib/hub/hubServer.ts +204 -0
- package/src/api/lib/hub/identity.ts +47 -0
- package/src/api/lib/hub/journal.ts +181 -0
- package/src/api/lib/hub/lockfile.ts +105 -0
- package/src/api/lib/hub/mutationClaim.ts +296 -0
- package/src/api/lib/hub/mutationQueue.ts +37 -0
- package/src/api/lib/hub/mutations.ts +164 -0
- package/src/api/lib/impact.ts +234 -0
- package/src/api/lib/reconciliationFlag.ts +338 -0
- package/src/api/lib/roadmapStore.ts +26 -2
- package/src/api/lib/sourceIndex/build.ts +161 -0
- package/src/api/lib/sourceIndex/query.ts +80 -0
- package/src/api/lib/sourceIndex/store.ts +128 -0
- package/src/api/lib/sourceIndex/types.ts +46 -0
- package/src/api/lib/tenboFs.ts +59 -1
- package/src/api/lib/validator.ts +49 -0
- package/src/api/plugin.ts +20 -0
- package/src/api/routes/hubHealth.ts +27 -0
- package/src/api/routes/hubMutate.ts +43 -0
- package/src/api/routes/items.ts +27 -9
- package/src/types.ts +44 -2
- package/src/ui/ItemModal/EnrichmentSections.tsx +18 -1
- package/vite.config.ts +0 -1
- package/scripts/bin-output.test.ts +0 -153
- package/scripts/commit-ready.test.ts +0 -47
- package/scripts/compute-metrics.test.ts +0 -35
- package/scripts/context.test.ts +0 -77
- package/scripts/hook.test.ts +0 -144
- package/scripts/item.test.ts +0 -234
- package/scripts/items.test.ts +0 -157
- package/scripts/next-id.test.ts +0 -128
- package/scripts/next.test.ts +0 -92
- package/scripts/validate-cli.test.ts +0 -152
- package/scripts/work-queue.test.ts +0 -91
- package/src/api/lib/contextResolver.test.ts +0 -161
- package/src/api/lib/health/agingTodos.test.ts +0 -32
- package/src/api/lib/health/archCompliance.test.ts +0 -26
- package/src/api/lib/health/collectAll.test.ts +0 -110
- package/src/api/lib/health/config.test.ts +0 -45
- package/src/api/lib/health/coupling.test.ts +0 -40
- package/src/api/lib/health/deadCode.test.ts +0 -27
- package/src/api/lib/health/docDrift.test.ts +0 -72
- package/src/api/lib/health/hotspotFiles.test.ts +0 -49
- package/src/api/lib/health/importGraph.test.ts +0 -73
- package/src/api/lib/health/layerFiles.test.ts +0 -46
- package/src/api/lib/health/redundancy.test.ts +0 -24
- package/src/api/lib/health/testCoverage.test.ts +0 -33
- package/src/api/lib/health/types.test.ts +0 -36
- package/src/api/lib/metrics.test.ts +0 -81
- package/src/api/lib/metricsRefresh.test.ts +0 -54
- package/src/api/lib/parseCache.test.ts +0 -96
- package/src/api/lib/phases.test.ts +0 -90
- package/src/api/lib/priority.test.ts +0 -54
- package/src/api/lib/roadmapStore.test.ts +0 -163
- package/src/api/lib/tenboFs.layerContent.test.ts +0 -36
- package/src/api/lib/tenboFs.v2.test.ts +0 -86
- package/src/api/lib/tenboFs.workspaceContent.test.ts +0 -42
- package/src/api/lib/validator.docUpdate.test.ts +0 -99
- package/src/api/lib/validator.duplicateIds.test.ts +0 -89
- package/src/api/lib/validator.goalRef.test.ts +0 -76
- package/src/api/lib/validator.phases.test.ts +0 -98
- package/src/api/lib/validator.preflightViolations.test.ts +0 -67
- package/src/api/lib/validator.relationships.test.ts +0 -132
- package/src/api/lib/validator.specLinks.test.ts +0 -100
- package/src/api/lib/validator.v2.test.ts +0 -55
- package/src/api/lib/validator.verification.test.ts +0 -52
- package/src/api/routes/state.test.ts +0 -148
- package/src/router/useHashRoute.test.ts +0 -69
- package/src/test-setup.ts +0 -1
- package/src/ui/FindingModal/FindingModal.test.tsx +0 -36
- package/src/ui/HealthPage/HealthPage.test.tsx +0 -71
- package/src/ui/HealthPage/severity.test.ts +0 -46
- package/src/ui/LayerDetailPage/LayerDetailPage.test.tsx +0 -30
- package/src/ui/LayerPage/isTemplateOnly.test.ts +0 -45
package/README.md
CHANGED
|
@@ -33,6 +33,10 @@ Project overview, principles, and glossary alongside per-layer narratives, inten
|
|
|
33
33
|
|
|
34
34
|
Surfaces the things that would otherwise become tech debt nobody mentions: oversized layers (hotspots), code-map references that no longer match real files (doc drift), unreferenced files, coupling violations, dead code. Each finding carries a severity, the file it points at, and a suggested fix.
|
|
35
35
|
|
|
36
|
+
Some health findings include generated graph evidence such as importers, exports,
|
|
37
|
+
and layer ownership. This evidence is rebuilt from source and `.tenbo/` metadata;
|
|
38
|
+
it is not separate project memory.
|
|
39
|
+
|
|
36
40
|
## CLI tools
|
|
37
41
|
|
|
38
42
|
The same package ships commands the skill uses behind the scenes — also runnable directly:
|
|
@@ -46,6 +50,8 @@ npx tenbo-dashboard item link-commit sk-030 7fc09a5
|
|
|
46
50
|
npx tenbo-dashboard items --status done --verification pending_live --json
|
|
47
51
|
npx tenbo-dashboard next --json
|
|
48
52
|
npx tenbo-dashboard context feature --query "help me build X" --json
|
|
53
|
+
npx tenbo-dashboard impact --json # Map git changes to affected layers/docs/items
|
|
54
|
+
npx tenbo-dashboard index --json # Rebuild the derived source index
|
|
49
55
|
npx tenbo-dashboard validate # Schema + consistency checks
|
|
50
56
|
npx tenbo-dashboard init-check # Strict completeness check after fresh init
|
|
51
57
|
npx tenbo-dashboard metrics --all # Recompute scope metrics + health findings
|
package/bin/tenbo-dashboard.mjs
CHANGED
|
@@ -43,13 +43,20 @@ const commands = {
|
|
|
43
43
|
sync: 'scripts/sync.ts',
|
|
44
44
|
archive: 'scripts/archive.ts',
|
|
45
45
|
'commit-ready': 'scripts/commit-ready.ts',
|
|
46
|
+
'commit-context': 'scripts/commit-context.ts',
|
|
46
47
|
item: 'scripts/item.ts',
|
|
47
48
|
items: 'scripts/items.ts',
|
|
48
49
|
list: 'scripts/items.ts',
|
|
49
50
|
next: 'scripts/next.ts',
|
|
50
51
|
'work-queue': 'scripts/work-queue.ts',
|
|
51
52
|
context: 'scripts/context.ts',
|
|
53
|
+
impact: 'scripts/impact.ts',
|
|
54
|
+
index: 'scripts/index.ts',
|
|
55
|
+
'code-map': 'scripts/code-map.ts',
|
|
56
|
+
reminder: 'scripts/reminder.ts',
|
|
52
57
|
hook: 'scripts/hook.ts',
|
|
58
|
+
reconcile: 'scripts/reconcile.ts',
|
|
59
|
+
hub: 'scripts/hub.ts',
|
|
53
60
|
};
|
|
54
61
|
|
|
55
62
|
// Documented aliases for the bare-launch behavior. Users (and agents) reading
|
|
@@ -97,6 +104,15 @@ ${topLevelItemHelpLines().join('\n')}
|
|
|
97
104
|
[--type <type>] [--json]
|
|
98
105
|
tenbo-dashboard context feature Fetch agent planning context for a natural-language request
|
|
99
106
|
--query "<request>" [--json]
|
|
107
|
+
tenbo-dashboard context session Deterministic session-gate briefing bundle [--json]
|
|
108
|
+
tenbo-dashboard context item <id> Deterministic per-item context bundle [--json]
|
|
109
|
+
tenbo-dashboard impact Map git changes to affected layers, docs, items,
|
|
110
|
+
and verification checks [--since <ref>] [--json]
|
|
111
|
+
tenbo-dashboard index Build or refresh the derived source index [--if-stale] [--json]
|
|
112
|
+
tenbo-dashboard code-map generate Regenerate the auto-generated structural region of a
|
|
113
|
+
layer's code-map.md from the source index
|
|
114
|
+
[--scope <id>] [--layer <id>] [--check] [--json]
|
|
115
|
+
tenbo-dashboard reminder print Print advisory session reminder text [--json]
|
|
100
116
|
tenbo-dashboard validate Run validation rules
|
|
101
117
|
tenbo-dashboard init-check Strict completeness check for fresh init (errors on missing skeletons, file_count:0, etc)
|
|
102
118
|
tenbo-dashboard next-id <prefix> Allocate next roadmap item ID
|
|
@@ -104,10 +120,28 @@ ${topLevelItemHelpLines().join('\n')}
|
|
|
104
120
|
tenbo-dashboard archive Move old done/dropped items to roadmap-archive.yaml
|
|
105
121
|
[--scope <id>] [--days 30] [--max 20]
|
|
106
122
|
tenbo-dashboard hook install Install opt-in pre-commit validation hook
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
(or 'prepare-commit-msg' for commit-context
|
|
124
|
+
suggestions, or 'post-commit' for doc-flag
|
|
125
|
+
detection) [--dry-run] [--force]
|
|
126
|
+
tenbo-dashboard hook uninstall Remove a tenbo hook (idempotent)
|
|
127
|
+
[pre-commit|prepare-commit-msg|post-commit]
|
|
109
128
|
tenbo-dashboard commit-ready Report branch, diff, validation, and staging gates
|
|
110
129
|
without committing [--json]
|
|
130
|
+
tenbo-dashboard commit-context Propose roadmap item refs + a draft commit message
|
|
131
|
+
from the pending diff [--since <ref>] [--json] [--hook-format]
|
|
132
|
+
tenbo-dashboard reconcile flag Map a commit's diff to affected layers and append
|
|
133
|
+
pending-reconciliation doc-flag entries
|
|
134
|
+
[--since <ref>] [--dry-run] [--json]
|
|
135
|
+
tenbo-dashboard reconcile clear Remove pending-reconciliation entries once a doc
|
|
136
|
+
update lands [--layer <scope:layer>] [--commit <sha>]
|
|
137
|
+
tenbo-dashboard hub start Run a headless, API-only hub server in the
|
|
138
|
+
foreground (health+mutate only, no browser UI)
|
|
139
|
+
[--port <n>]
|
|
140
|
+
tenbo-dashboard hub ensure Idempotent: start a hub for this repo if none
|
|
141
|
+
is running yet, else no-op [--json]
|
|
142
|
+
tenbo-dashboard hub stop Stop this repo's running hub, if any [--json]
|
|
143
|
+
tenbo-dashboard hub status Report whether a hub is running
|
|
144
|
+
(pid/port/uptime) [--json]
|
|
111
145
|
tenbo-dashboard --version Print package version
|
|
112
146
|
tenbo-dashboard help Show this help
|
|
113
147
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tenbo-dashboard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Local-first architecture dashboard and CLI tools for .tenbo/ repos",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,6 +30,9 @@
|
|
|
30
30
|
"bin/",
|
|
31
31
|
"src/",
|
|
32
32
|
"scripts/",
|
|
33
|
+
"!**/*.test.ts",
|
|
34
|
+
"!**/*.test.tsx",
|
|
35
|
+
"!src/test-setup.ts",
|
|
33
36
|
"index.html",
|
|
34
37
|
"vite.config.ts",
|
|
35
38
|
"tsconfig.json"
|
|
@@ -47,7 +50,7 @@
|
|
|
47
50
|
"@dnd-kit/sortable": "^8.0.0",
|
|
48
51
|
"@dnd-kit/utilities": "^3.2.2",
|
|
49
52
|
"@parcel/watcher": "^2.5.6",
|
|
50
|
-
"@vitejs/plugin-react": "^4.
|
|
53
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
51
54
|
"@xyflow/react": "^12.10.2",
|
|
52
55
|
"chokidar": "^3.6.0",
|
|
53
56
|
"dagre": "^0.8.5",
|
|
@@ -59,9 +62,9 @@
|
|
|
59
62
|
"react-markdown": "^9.0.1",
|
|
60
63
|
"remark-gfm": "^4.0.0",
|
|
61
64
|
"ts-morph": "^25",
|
|
62
|
-
"tsx": "^4.
|
|
65
|
+
"tsx": "^4.22.4",
|
|
63
66
|
"typescript": "^5.5.4",
|
|
64
|
-
"vite": "^
|
|
67
|
+
"vite": "^6.4.3",
|
|
65
68
|
"yaml": "^2.5.1"
|
|
66
69
|
},
|
|
67
70
|
"devDependencies": {
|
package/scripts/cliArgs.ts
CHANGED
|
@@ -16,12 +16,25 @@ export function readRepeated(args: string[], flag: string): string[] {
|
|
|
16
16
|
return out;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export
|
|
19
|
+
export interface PositionalArgsOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Flags that consume the token immediately after them (e.g. `--status
|
|
22
|
+
* done`). Any `--flag` NOT in this set is treated as boolean/valueless
|
|
23
|
+
* (e.g. `--json`, `--check`) — the token that follows it is left in place
|
|
24
|
+
* as a positional, regardless of where the flag appears among the args.
|
|
25
|
+
* Defaults to no value-taking flags, so bare `positionalArgs(args)` never
|
|
26
|
+
* consumes a token after a `--flag`.
|
|
27
|
+
*/
|
|
28
|
+
valueFlags?: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function positionalArgs(args: string[], options: PositionalArgsOptions = {}): string[] {
|
|
32
|
+
const valueFlags = new Set(options.valueFlags ?? []);
|
|
20
33
|
const out: string[] = [];
|
|
21
34
|
for (let i = 0; i < args.length; i++) {
|
|
22
35
|
const arg = args[i];
|
|
23
36
|
if (arg.startsWith('--')) {
|
|
24
|
-
if (
|
|
37
|
+
if (valueFlags.has(arg) && i + 1 < args.length) i++;
|
|
25
38
|
continue;
|
|
26
39
|
}
|
|
27
40
|
out.push(arg);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { generateCodeMaps, isCodeMapGeneratorError } from '../src/api/lib/codeMapGenerator';
|
|
2
|
+
import { hasFlag, readOption } from './cliArgs';
|
|
3
|
+
import { fail, handleCliError, isMain, misuse, repoRootFromCwd, runMain, type CliResult } from './cliResult';
|
|
4
|
+
|
|
5
|
+
const USAGE = 'Usage: tenbo-dashboard code-map generate [--scope <id>] [--layer <id>] [--check] [--json]';
|
|
6
|
+
|
|
7
|
+
export function runCodeMapCli(repoRoot: string, args: string[]): CliResult {
|
|
8
|
+
const json = hasFlag(args, '--json');
|
|
9
|
+
const command = args.find((arg) => !arg.startsWith('--'));
|
|
10
|
+
|
|
11
|
+
if (command !== 'generate') {
|
|
12
|
+
return misuse(USAGE, json);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const scope = readOption(args, '--scope');
|
|
16
|
+
const layer = readOption(args, '--layer');
|
|
17
|
+
const check = hasFlag(args, '--check');
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const result = generateCodeMaps(repoRoot, { scope, layer, check });
|
|
21
|
+
const staleCount = result.stale_layers.length;
|
|
22
|
+
const isStaleFailure = check && staleCount > 0;
|
|
23
|
+
const summary = check
|
|
24
|
+
? (isStaleFailure
|
|
25
|
+
? `code-map: ${staleCount} layer(s) stale: ${result.stale_layers.join(', ')}\n`
|
|
26
|
+
: `code-map: ${result.layers.length} layer(s) checked, all fresh\n`)
|
|
27
|
+
: `code-map: ${result.layers.length} layer(s) generated (${staleCount} changed)\n`;
|
|
28
|
+
|
|
29
|
+
if (json) {
|
|
30
|
+
return { stdout: `${JSON.stringify(result, null, 2)}\n`, stderr: '', exitCode: isStaleFailure ? 1 : 0 };
|
|
31
|
+
}
|
|
32
|
+
return isStaleFailure
|
|
33
|
+
? { stdout: '', stderr: summary, exitCode: 1 }
|
|
34
|
+
: { stdout: summary, stderr: '', exitCode: 0 };
|
|
35
|
+
} catch (err) {
|
|
36
|
+
if (isCodeMapGeneratorError(err)) {
|
|
37
|
+
return fail(err.code, err.message, json);
|
|
38
|
+
}
|
|
39
|
+
return handleCliError(err, json);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (isMain(import.meta.url)) {
|
|
44
|
+
runMain(runCodeMapCli(repoRootFromCwd(), process.argv.slice(2)));
|
|
45
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { resolveCommitContext } from '../src/api/lib/commitContext';
|
|
2
|
+
import { hasFlag, readOption } from './cliArgs';
|
|
3
|
+
import { isMain, misuse, repoRootFromCwd, runMain, serialize, type CliResult } from './cliResult';
|
|
4
|
+
|
|
5
|
+
export function runCommitContextCli(repoRoot: string, args: string[]): CliResult {
|
|
6
|
+
const json = hasFlag(args, '--json');
|
|
7
|
+
const hookFormat = hasFlag(args, '--hook-format');
|
|
8
|
+
const since = readOption(args, '--since');
|
|
9
|
+
if (args.includes('--since') && (!since || since.startsWith('--'))) {
|
|
10
|
+
return misuse('Usage: tenbo-dashboard commit-context [--since <ref>] [--json] [--hook-format]', json);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// resolveCommitContext is fail-open by design (never throws), so there is
|
|
14
|
+
// no try/catch here — any internal failure already surfaces as a payload
|
|
15
|
+
// with empty suggestions and a `note` explaining why.
|
|
16
|
+
const payload = resolveCommitContext(repoRoot, { since });
|
|
17
|
+
|
|
18
|
+
if (hookFormat) {
|
|
19
|
+
return { stdout: payload.hook_format ? `${payload.hook_format}\n` : '', stderr: '', exitCode: 0 };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const text = payload.suggestions.length
|
|
23
|
+
? `${payload.suggestions.length} suggestion(s):\n${payload.suggestions
|
|
24
|
+
.map((s) => ` ${s.id} (${s.status}) ${s.title} — ${s.reason}`)
|
|
25
|
+
.join('\n')}\n\nDraft message:\n${payload.draft_message}\n`
|
|
26
|
+
: `${payload.note}\n${payload.draft_message ? `\nDraft message:\n${payload.draft_message}\n` : ''}`;
|
|
27
|
+
|
|
28
|
+
return serialize(payload, json, text);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isMain(import.meta.url)) {
|
|
32
|
+
runMain(runCommitContextCli(repoRootFromCwd(), process.argv.slice(2)));
|
|
33
|
+
}
|
package/scripts/context.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { resolveFeatureContext } from '../src/api/lib/contextResolver';
|
|
2
|
-
import { hasFlag, readOption } from './cliArgs';
|
|
1
|
+
import { resolveFeatureContext, resolveItemContext, resolveSessionContext } from '../src/api/lib/contextResolver';
|
|
2
|
+
import { hasFlag, positionalArgs, readOption } from './cliArgs';
|
|
3
3
|
import { handleCliError, isMain, misuse, repoRootFromCwd, runMain, serialize, type CliResult } from './cliResult';
|
|
4
4
|
|
|
5
|
+
const USAGE = 'Usage: tenbo context <feature|session|item> ... [--json]\n'
|
|
6
|
+
+ ' tenbo context feature --query "<request>" [--json]\n'
|
|
7
|
+
+ ' tenbo context session [--json]\n'
|
|
8
|
+
+ ' tenbo context item <id> [--json]';
|
|
9
|
+
|
|
5
10
|
export function runContextCli(repoRoot: string, args: string[]): CliResult {
|
|
6
11
|
const json = hasFlag(args, '--json');
|
|
7
12
|
const command = args.find((arg) => !arg.startsWith('--'));
|
|
@@ -18,7 +23,31 @@ export function runContextCli(repoRoot: string, args: string[]): CliResult {
|
|
|
18
23
|
);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
if (command === 'session') {
|
|
27
|
+
const bundle = resolveSessionContext(repoRoot);
|
|
28
|
+
return serialize(
|
|
29
|
+
bundle,
|
|
30
|
+
json,
|
|
31
|
+
`now: ${bundle.now.count} (${bundle.stale.now.length} stale), stale next: ${bundle.stale.next.length}\n`,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (command === 'item') {
|
|
36
|
+
// `item` itself has no value-taking flags (only boolean --json), so
|
|
37
|
+
// any --flag encountered here never consumes the following token —
|
|
38
|
+
// this keeps `context item --json <id>` and `context item <id>
|
|
39
|
+
// --json` equivalent (td-032).
|
|
40
|
+
const [, itemId] = positionalArgs(args);
|
|
41
|
+
if (!itemId) return misuse('Usage: tenbo context item <id> [--json]', json);
|
|
42
|
+
const bundle = resolveItemContext(repoRoot, itemId);
|
|
43
|
+
return serialize(
|
|
44
|
+
bundle,
|
|
45
|
+
json,
|
|
46
|
+
`${bundle.item_id}: ${bundle.item.title} (${bundle.item.status})\n`,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return misuse(USAGE, json);
|
|
22
51
|
} catch (err) {
|
|
23
52
|
return handleCliError(err, json);
|
|
24
53
|
}
|