@smartmemory/compose 0.1.43-beta → 0.1.44-beta

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.
Files changed (2) hide show
  1. package/bin/compose.js +108 -0
  2. package/package.json +1 -1
package/bin/compose.js CHANGED
@@ -119,6 +119,8 @@ if (!cmd || cmd === '--help' || cmd === '-h') {
119
119
  console.log(' roadmap generate Regenerate ROADMAP.md from feature.json files')
120
120
  console.log(' roadmap migrate Extract ROADMAP.md entries into feature.json files')
121
121
  console.log(' roadmap check Verify feature.json and ROADMAP.md are in sync')
122
+ console.log(' items List vision items from local state (no server)')
123
+ console.log(' items show <id> Show detail for a specific vision item')
122
124
  console.log(' triage Analyze a feature and recommend build profile')
123
125
  console.log(' qa-scope Show affected routes from a feature\'s changed files')
124
126
  console.log(' init Initialize Compose in the current project')
@@ -2692,6 +2694,112 @@ if (cmd === 'build') {
2692
2694
  process.exit(1)
2693
2695
  }
2694
2696
 
2697
+ } else if (cmd === 'items') {
2698
+ // ---------------------------------------------------------------------------
2699
+ // compose items — read vision-state.json directly (no server required)
2700
+ // ---------------------------------------------------------------------------
2701
+ const itemsSub = args[0] && !args[0].startsWith('-') ? args[0] : 'list'
2702
+ const jsonFlag = args.includes('--json')
2703
+
2704
+ const { root: itemsCwd } = resolveCwdWithWorkspace(args)
2705
+ const vsPath = join(itemsCwd, '.compose', 'data', 'vision-state.json')
2706
+
2707
+ if (!existsSync(vsPath)) {
2708
+ console.error('No vision state found at .compose/data/vision-state.json')
2709
+ console.error('Run `compose start` at least once to generate it, then you can use `compose items` offline.')
2710
+ process.exit(1)
2711
+ }
2712
+
2713
+ let visionState
2714
+ try {
2715
+ visionState = JSON.parse(readFileSync(vsPath, 'utf-8'))
2716
+ } catch (err) {
2717
+ console.error(`Failed to read vision state: ${err.message}`)
2718
+ process.exit(1)
2719
+ }
2720
+
2721
+ const allItems = visionState.items || []
2722
+
2723
+ if (itemsSub === 'list') {
2724
+ if (jsonFlag) {
2725
+ console.log(JSON.stringify(allItems, null, 2))
2726
+ process.exit(0)
2727
+ }
2728
+
2729
+ if (allItems.length === 0) {
2730
+ console.log('No items found.')
2731
+ process.exit(0)
2732
+ }
2733
+
2734
+ // Table output: id (truncated), title, status, type
2735
+ const header = { id: 'ID', title: 'TITLE', status: 'STATUS', type: 'TYPE' }
2736
+ const rows = allItems.map(it => ({
2737
+ id: (it.id || '').slice(0, 8),
2738
+ title: (it.title || '(untitled)').slice(0, 50),
2739
+ status: it.status || '-',
2740
+ type: it.type || '-',
2741
+ }))
2742
+
2743
+ // Compute column widths
2744
+ const cols = ['id', 'title', 'status', 'type']
2745
+ const widths = {}
2746
+ for (const c of cols) {
2747
+ widths[c] = Math.max(header[c].length, ...rows.map(r => r[c].length))
2748
+ }
2749
+
2750
+ const pad = (s, w) => s + ' '.repeat(Math.max(0, w - s.length))
2751
+ const line = cols.map(c => pad(header[c], widths[c])).join(' ')
2752
+ console.log(line)
2753
+ console.log(cols.map(c => '-'.repeat(widths[c])).join(' '))
2754
+ for (const r of rows) {
2755
+ console.log(cols.map(c => pad(r[c], widths[c])).join(' '))
2756
+ }
2757
+ process.exit(0)
2758
+
2759
+ } else if (itemsSub === 'show') {
2760
+ const positionalArgs = args.filter(a => !a.startsWith('-'))
2761
+ const showId = positionalArgs[1]
2762
+ if (!showId) {
2763
+ console.error('Usage: compose items show <id>')
2764
+ process.exit(1)
2765
+ }
2766
+
2767
+ const matches = allItems.filter(it => it.id === showId || it.id.startsWith(showId))
2768
+ if (matches.length > 1) {
2769
+ console.error(`Ambiguous ID prefix '${showId}' matches ${matches.length} items:`)
2770
+ for (const m of matches) console.error(` ${(m.id || '').slice(0, 8)} ${m.title || '(untitled)'}`)
2771
+ process.exit(1)
2772
+ }
2773
+ const match = matches[0]
2774
+ if (!match) {
2775
+ console.error(`No item found matching: ${showId}`)
2776
+ process.exit(1)
2777
+ }
2778
+
2779
+ if (jsonFlag) {
2780
+ console.log(JSON.stringify(match, null, 2))
2781
+ } else {
2782
+ for (const [key, val] of Object.entries(match)) {
2783
+ if (val == null) continue
2784
+ if (typeof val === 'object') {
2785
+ console.log(`${key}: ${JSON.stringify(val)}`)
2786
+ } else {
2787
+ console.log(`${key}: ${val}`)
2788
+ }
2789
+ }
2790
+ }
2791
+ process.exit(0)
2792
+
2793
+ } else {
2794
+ console.error(`Unknown items subcommand: ${itemsSub}`)
2795
+ console.error('Usage:')
2796
+ console.error(' compose items List all items')
2797
+ console.error(' compose items list List all items')
2798
+ console.error(' compose items show <id> Show detail for a specific item')
2799
+ console.error(' --json Output as JSON')
2800
+ process.exit(1)
2801
+ }
2802
+
2695
2803
  } else {
2696
2804
  console.error(`Unknown command: ${cmd}`)
2697
2805
  process.exit(1)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartmemory/compose",
3
- "version": "0.1.43-beta",
3
+ "version": "0.1.44-beta",
4
4
  "description": "Structured AI dev pipeline — goal-to-product orchestration with gates, iteration loops, and feature lifecycle management.",
5
5
  "author": "SmartMemory",
6
6
  "license": "MIT",