@smartmemory/compose 0.2.48-beta → 0.2.50-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 (96) hide show
  1. package/.claude/skills/compose/SKILL.md +2 -0
  2. package/.compose-deps.json +13 -0
  3. package/bin/compose.js +35 -20
  4. package/dist/assets/{App-D7E7S49Q.js → App-Bxyif1yv.js} +160 -160
  5. package/dist/assets/{arc-LOW60tiI.js → arc-DeHak63Z.js} +1 -1
  6. package/dist/assets/{architectureDiagram-3BPJPVTR-BDY00hRy.js → architectureDiagram-3BPJPVTR-C5Nkyl9y.js} +1 -1
  7. package/dist/assets/{blockDiagram-GPEHLZMM-DiC_6ktq.js → blockDiagram-GPEHLZMM-BilnUBG2.js} +1 -1
  8. package/dist/assets/{c4Diagram-AAUBKEIU-CXZC8woU.js → c4Diagram-AAUBKEIU-BsFJmPuS.js} +1 -1
  9. package/dist/assets/channel-ZgbQ1k0u.js +1 -0
  10. package/dist/assets/{chunk-2J33WTMH-b8Rdk4S-.js → chunk-2J33WTMH-AEu6HIoY.js} +1 -1
  11. package/dist/assets/{chunk-4BX2VUAB-BSxn03f-.js → chunk-4BX2VUAB-XO4S2_89.js} +1 -1
  12. package/dist/assets/{chunk-55IACEB6-uUk1WzZ1.js → chunk-55IACEB6-CtFSLInj.js} +1 -1
  13. package/dist/assets/{chunk-727SXJPM-zvXhT6iZ.js → chunk-727SXJPM-CZeBRpM9.js} +1 -1
  14. package/dist/assets/{chunk-AQP2D5EJ-B6GCyrIp.js → chunk-AQP2D5EJ-_vmxcBc4.js} +1 -1
  15. package/dist/assets/{chunk-FMBD7UC4-DlhrqkBp.js → chunk-FMBD7UC4-BMGd_Y9a.js} +1 -1
  16. package/dist/assets/{chunk-ND2GUHAM-lo_8kNzw.js → chunk-ND2GUHAM-BlrOECEr.js} +1 -1
  17. package/dist/assets/{chunk-QZHKN3VN-on-yD-C0.js → chunk-QZHKN3VN-DHhUJ8RK.js} +1 -1
  18. package/dist/assets/classDiagram-4FO5ZUOK-KXxOorUx.js +1 -0
  19. package/dist/assets/classDiagram-v2-Q7XG4LA2-KXxOorUx.js +1 -0
  20. package/dist/assets/{cose-bilkent-S5V4N54A-DxV7Y2bU.js → cose-bilkent-S5V4N54A-C3M0mZqk.js} +1 -1
  21. package/dist/assets/{dagre-BM42HDAG-BHf9sURy.js → dagre-BM42HDAG-DJlm4fEk.js} +1 -1
  22. package/dist/assets/{diagram-2AECGRRQ-R9Puxzlh.js → diagram-2AECGRRQ-BmcONQG5.js} +1 -1
  23. package/dist/assets/{diagram-5GNKFQAL-BbjlClKx.js → diagram-5GNKFQAL-5JbWGIwd.js} +1 -1
  24. package/dist/assets/{diagram-KO2AKTUF-r89Mx4m1.js → diagram-KO2AKTUF-DAnIvyI0.js} +1 -1
  25. package/dist/assets/{diagram-LMA3HP47-CstVDJZ3.js → diagram-LMA3HP47-Bmh7tvmI.js} +1 -1
  26. package/dist/assets/{diagram-OG6HWLK6-xmX57FKh.js → diagram-OG6HWLK6-hnHVMNnk.js} +1 -1
  27. package/dist/assets/{erDiagram-TEJ5UH35-DhLPxvrl.js → erDiagram-TEJ5UH35-AMDitV0b.js} +1 -1
  28. package/dist/assets/{flowDiagram-I6XJVG4X-BExoUaNm.js → flowDiagram-I6XJVG4X-C0t2ZGQv.js} +1 -1
  29. package/dist/assets/{ganttDiagram-6RSMTGT7-BEXa5a22.js → ganttDiagram-6RSMTGT7-BPlM-BEN.js} +1 -1
  30. package/dist/assets/{gitGraphDiagram-PVQCEYII-Cbes9api.js → gitGraphDiagram-PVQCEYII-Lv_YTxnb.js} +1 -1
  31. package/dist/assets/index-COq21Zym.js +119 -0
  32. package/dist/assets/{infoDiagram-5YYISTIA-UBm4ssfm.js → infoDiagram-5YYISTIA-Dul1vdUm.js} +1 -1
  33. package/dist/assets/{ishikawaDiagram-YF4QCWOH-CksBYHCF.js → ishikawaDiagram-YF4QCWOH-CCBwgjFs.js} +1 -1
  34. package/dist/assets/{journeyDiagram-JHISSGLW-CKHkIHky.js → journeyDiagram-JHISSGLW-zUJN38EU.js} +1 -1
  35. package/dist/assets/{kanban-definition-UN3LZRKU-CEahMFzE.js → kanban-definition-UN3LZRKU-BNxWi-8J.js} +1 -1
  36. package/dist/assets/{linear-CqLVtYRk.js → linear-CRH9b4g7.js} +1 -1
  37. package/dist/assets/{mindmap-definition-RKZ34NQL-C61zWt4M.js → mindmap-definition-RKZ34NQL-DolYwq7Y.js} +1 -1
  38. package/dist/assets/{pieDiagram-4H26LBE5-BIpZHyJW.js → pieDiagram-4H26LBE5-oxNfr2TX.js} +1 -1
  39. package/dist/assets/{quadrantDiagram-W4KKPZXB-Db7nRbZm.js → quadrantDiagram-W4KKPZXB-BmZCvD-z.js} +1 -1
  40. package/dist/assets/{requirementDiagram-4Y6WPE33-BQqFCAr0.js → requirementDiagram-4Y6WPE33-DsXZ05jo.js} +1 -1
  41. package/dist/assets/{sankeyDiagram-5OEKKPKP-D-oAAMci.js → sankeyDiagram-5OEKKPKP-DsnYaawP.js} +1 -1
  42. package/dist/assets/{sequenceDiagram-3UESZ5HK-Dc4Cp0Om.js → sequenceDiagram-3UESZ5HK-Dt5mu3g8.js} +1 -1
  43. package/dist/assets/{stateDiagram-AJRCARHV-B5DkQ8Pr.js → stateDiagram-AJRCARHV-BFR5ZINQ.js} +1 -1
  44. package/dist/assets/stateDiagram-v2-BHNVJYJU-BDrQD8fR.js +1 -0
  45. package/dist/assets/{timeline-definition-PNZ67QCA-DU9Fl-FW.js → timeline-definition-PNZ67QCA-Bvnhw58e.js} +1 -1
  46. package/dist/assets/{vennDiagram-CIIHVFJN-Bthz7siw.js → vennDiagram-CIIHVFJN-5WnyjZqf.js} +1 -1
  47. package/dist/assets/{wardley-L42UT6IY-nqdlFSIA.js → wardley-L42UT6IY-CTxW4xow.js} +1 -1
  48. package/dist/assets/{wardleyDiagram-YWT4CUSO-BJ1BC5zc.js → wardleyDiagram-YWT4CUSO-K8Y1EOvb.js} +1 -1
  49. package/dist/assets/{xychartDiagram-2RQKCTM6-Bib5JrbR.js → xychartDiagram-2RQKCTM6-BCShes6B.js} +1 -1
  50. package/dist/index.html +1 -1
  51. package/lib/build-all.js +2 -1
  52. package/lib/build.js +96 -6
  53. package/lib/checkpoint/checkpoint-writer.js +3 -2
  54. package/lib/completion-writer.js +38 -14
  55. package/lib/deps.js +98 -1
  56. package/lib/feature-json.js +14 -3
  57. package/lib/feature-validator.js +22 -9
  58. package/lib/feature-write-guard.js +5 -7
  59. package/lib/feature-writer.js +3 -3
  60. package/lib/followup-writer.js +2 -2
  61. package/lib/get-roadmap.js +2 -2
  62. package/lib/gsd.js +2 -1
  63. package/lib/ideabox.js +3 -2
  64. package/lib/journal-writer.js +3 -3
  65. package/lib/migrate-roadmap.js +2 -3
  66. package/lib/paths-core.js +47 -0
  67. package/lib/project-paths.js +46 -37
  68. package/lib/roadmap-gen.js +3 -4
  69. package/lib/roadmap-graph/collect.js +5 -5
  70. package/lib/roadmap-graph/index.js +2 -2
  71. package/lib/rtk.js +66 -0
  72. package/lib/state-migrations.js +211 -42
  73. package/lib/tracker/local-provider.js +2 -2
  74. package/lib/triage.js +7 -5
  75. package/lib/vision-writer.js +6 -13
  76. package/lib/xref-push.js +4 -4
  77. package/lib/xref-sync.js +4 -4
  78. package/package.json +1 -1
  79. package/server/compose-mcp-tools.js +9 -1
  80. package/server/design-routes.js +9 -4
  81. package/server/drift-axes.js +5 -3
  82. package/server/feature-scan.js +8 -2
  83. package/server/file-watcher.js +13 -7
  84. package/server/ideabox-routes.js +12 -11
  85. package/server/project-root.js +21 -4
  86. package/server/session-routes.js +2 -2
  87. package/server/stratum-sync.js +85 -9
  88. package/server/vision-routes.js +17 -2
  89. package/server/vision-server.js +4 -3
  90. package/server/vision-store.js +6 -11
  91. package/server/vision-utils.js +23 -4
  92. package/dist/assets/channel-Dh96pu1k.js +0 -1
  93. package/dist/assets/classDiagram-4FO5ZUOK-BCqpDcaS.js +0 -1
  94. package/dist/assets/classDiagram-v2-Q7XG4LA2-BCqpDcaS.js +0 -1
  95. package/dist/assets/index-DNuHtZwR.js +0 -123
  96. package/dist/assets/stateDiagram-v2-BHNVJYJU-BM1Uf6a_.js +0 -1
@@ -596,6 +596,8 @@ Authoritative list lives in `compose/.compose-deps.json`. Run `compose doctor` t
596
596
 
597
597
  The manifest declares 12 external skills/commands across `superpowers:*`, `interface-design:*`, `codex:review`, `refactor`, and `update-docs`. Each entry carries `id`, `required_for`, `install`, `fallback` (or null), and `optional`.
598
598
 
599
+ The manifest also has an optional `external_binaries` array for CLI tools (not skills). Today it declares `rtk` ([Rust Token Killer](https://github.com/rtk-ai/rtk), COMP-RTK-INTEROP) — a lossy output compressor compose routes its one LLM-bound `git diff` (the Codex review diff) through when present, degrading byte-identically when absent. `compose doctor` reports binaries alongside skills and surfaces each binary's `recommend` (for rtk: `rtk init -g`, which installs RTK's Claude Code hook so the agent's *own* Bash output is compressed too — the larger token win). Binary entries carry `id`, `detect`, `install`, `recommend` (or null), and `optional`; all are optional and never block the lifecycle.
600
+
599
601
  ### Degrade pattern
600
602
 
601
603
  At lifecycle entry (Phase 1), run `compose doctor --json`. For each missing dep:
@@ -85,5 +85,18 @@
85
85
  "fallback": "manual TODO surfaced in implementation report",
86
86
  "optional": true
87
87
  }
88
+ ],
89
+ "external_binaries": [
90
+ {
91
+ "id": "rtk",
92
+ "detect": "rtk --version",
93
+ "required_for": [
94
+ "LLM-bound git-diff compression (build review)",
95
+ "agent Bash output compression via `rtk init -g` hook"
96
+ ],
97
+ "install": "brew install rtk (or: cargo install --git https://github.com/rtk-ai/rtk)",
98
+ "recommend": "rtk init -g",
99
+ "optional": true
100
+ }
88
101
  ]
89
102
  }
package/bin/compose.js CHANGED
@@ -17,6 +17,7 @@ import { fileURLToPath } from 'url'
17
17
  import { findProjectRoot } from '../server/find-root.js'
18
18
  import { resolveWorkspace, getWorkspaceFlag } from '../lib/resolve-workspace.js'
19
19
  import { resolvePort } from '../lib/resolve-port.js'
20
+ import { resolveRoadmapPath, resolveFeaturesPath, resolveContextPathFromConfig, resolveFeaturesPathFromConfig, resolveRoadmapPathFromConfig } from '../lib/project-paths.js'
20
21
 
21
22
  const __dirname = dirname(fileURLToPath(import.meta.url))
22
23
  const PACKAGE_ROOT = resolve(__dirname, '..')
@@ -81,7 +82,7 @@ function resolveCwdWithWorkspace(args) {
81
82
  // --team flag (COMP-TEAMS)
82
83
  // ---------------------------------------------------------------------------
83
84
  import { parseTeamFlag } from '../lib/team-flag.js';
84
- import { loadDeps, checkExternalSkills, printDepReport, buildDepReport } from '../lib/deps.js';
85
+ import { loadDeps, checkExternalSkills, printDepReport, buildDepReport, checkExternalBinaries, printBinaryReport, buildBinaryReport } from '../lib/deps.js';
85
86
  import { checkLatestVersion } from '../lib/version-check.js';
86
87
 
87
88
  const [,, cmd, ...args] = process.argv
@@ -271,6 +272,7 @@ function syncSkills(agents) {
271
272
  if (deps) {
272
273
  const result = checkExternalSkills(deps)
273
274
  printDepReport(result)
275
+ printBinaryReport(checkExternalBinaries(deps))
274
276
  }
275
277
  }
276
278
 
@@ -302,7 +304,8 @@ async function runDoctor(flags = []) {
302
304
  // Single top-level JSON document — the deps report and the version block share one root
303
305
  // so consumers like `JSON.parse(stdout)` work. (Previously two concatenated objects.)
304
306
  const report = buildDepReport(result)
305
- console.log(JSON.stringify({ ...report, version: versionInfo }, null, 2))
307
+ const binaries = buildBinaryReport(checkExternalBinaries(deps))
308
+ console.log(JSON.stringify({ ...report, binaries, version: versionInfo }, null, 2))
306
309
  const allRequiredPresent = result.missing.every(d => d.optional)
307
310
  if (strict && !allRequiredPresent) process.exit(1)
308
311
  return
@@ -323,6 +326,7 @@ async function runDoctor(flags = []) {
323
326
  }
324
327
 
325
328
  const allRequiredPresent = printDepReport(result, { json: false, verbose })
329
+ printBinaryReport(checkExternalBinaries(deps))
326
330
  if (strict && !allRequiredPresent) process.exit(1)
327
331
  }
328
332
 
@@ -409,6 +413,7 @@ async function runInit(flags, cwdOverride) {
409
413
  },
410
414
  paths: {
411
415
  docs: 'docs',
416
+ roadmap: 'ROADMAP.md',
412
417
  features: 'docs/features',
413
418
  journal: 'docs/journal',
414
419
  context: 'docs/context',
@@ -444,8 +449,9 @@ async function runInit(flags, cwdOverride) {
444
449
  }
445
450
  }
446
451
 
447
- // 5b. Scaffold docs/context/ with ambient context templates
448
- const contextDir = join(cwd, config.paths.context)
452
+ // 5b. Scaffold docs/context/ with ambient context templates.
453
+ // COMP-PATHS-EXTERNAL: resolve from the in-memory config (may be relocated).
454
+ const contextDir = resolveContextPathFromConfig(cwd, config)
449
455
  mkdirSync(contextDir, { recursive: true })
450
456
  const contextTemplates = {
451
457
  'tech-stack.md': '# Tech Stack\n\nDescribe your technology stack here.\n',
@@ -461,8 +467,8 @@ async function runInit(flags, cwdOverride) {
461
467
  }
462
468
 
463
469
  // 5c. Scaffold docs/product/ideabox.md if absent
464
- const ideaboxRel = config.paths.ideabox || 'docs/product/ideabox.md'
465
- const ideaboxDest = join(cwd, ideaboxRel)
470
+ const { resolveIdeaboxPath: _resolveIdeaboxPathInit } = await import('../lib/project-paths.js')
471
+ const ideaboxDest = _resolveIdeaboxPathInit(cwd)
466
472
  if (!existsSync(ideaboxDest)) {
467
473
  mkdirSync(dirname(ideaboxDest), { recursive: true })
468
474
  const { IDEABOX_TEMPLATE } = await import('../lib/ideabox.js')
@@ -510,8 +516,10 @@ async function runInit(flags, cwdOverride) {
510
516
  }
511
517
  }
512
518
 
513
- // 7. Scaffold ROADMAP.md from template if absent
514
- const roadmapDest = join(cwd, 'ROADMAP.md')
519
+ // 7. Scaffold ROADMAP.md from template if absent. COMP-PATHS-EXTERNAL:
520
+ // honor a configured (possibly relocated) paths.roadmap instead of always
521
+ // seeding <cwd>/ROADMAP.md. Byte-identical for the default.
522
+ const roadmapDest = resolveRoadmapPathFromConfig(cwd, config)
515
523
  if (!existsSync(roadmapDest)) {
516
524
  const roadmapSrc = join(PACKAGE_ROOT, 'templates', 'ROADMAP.md')
517
525
  if (existsSync(roadmapSrc)) {
@@ -939,10 +947,12 @@ if (cmd === 'feature') {
939
947
 
940
948
  let config = {}
941
949
  try { config = JSON.parse(readFileSync(configPath, 'utf-8')) } catch {}
942
- const featuresDir = config.paths?.features || 'docs/features'
950
+ // COMP-PATHS-EXTERNAL: absolute features dir (may be relocated outside cwd).
951
+ // Never join(cwd, …) below — that would re-root an absolute/../-escaping override.
952
+ const featuresDir = resolveFeaturesPath(cwd)
943
953
 
944
954
  // 1. Create feature folder + seed design doc
945
- const featureDir = join(cwd, featuresDir, featureCode)
955
+ const featureDir = join(featuresDir, featureCode)
946
956
  const designPath = join(featureDir, 'design.md')
947
957
 
948
958
  if (existsSync(designPath)) {
@@ -982,7 +992,7 @@ if (cmd === 'feature') {
982
992
  // Count existing features for complexity estimate
983
993
  const existingFeatureCount = (() => {
984
994
  try {
985
- const fdir = join(cwd, featuresDir)
995
+ const fdir = featuresDir
986
996
  if (!existsSync(fdir)) return 0
987
997
  return readdirSync(fdir, { withFileTypes: true })
988
998
  .filter(e => e.isDirectory() && existsSync(join(fdir, e.name, 'feature.json')))
@@ -1039,7 +1049,7 @@ _This is a seed design doc created by \`compose feature\`. The \`compose build\`
1039
1049
  console.log(`Created ${designPath}`)
1040
1050
 
1041
1051
  // 2. Add entry to ROADMAP.md
1042
- const roadmapPath = join(cwd, 'ROADMAP.md')
1052
+ const roadmapPath = resolveRoadmapPath(cwd)
1043
1053
  if (existsSync(roadmapPath)) {
1044
1054
  let roadmap = readFileSync(roadmapPath, 'utf-8')
1045
1055
 
@@ -1154,7 +1164,7 @@ if (cmd === 'roadmap') {
1154
1164
  const { checkRoundtrip, describeLossyDiff } = await import('../lib/roadmap-roundtrip.js')
1155
1165
  const { loadExternalPrefixes } = await import('../lib/project-paths.js')
1156
1166
  const { root: cwd } = resolveCwdWithWorkspace(args)
1157
- const roadmapPath = join(cwd, 'ROADMAP.md')
1167
+ const roadmapPath = resolveRoadmapPath(cwd)
1158
1168
  if (!existsSync(roadmapPath)) {
1159
1169
  console.error('No ROADMAP.md found. Run: compose roadmap generate')
1160
1170
  process.exit(1)
@@ -1347,7 +1357,7 @@ if (cmd === 'roadmap') {
1347
1357
  }
1348
1358
 
1349
1359
  const { root: cwd } = resolveCwdWithWorkspace(args)
1350
- const roadmapPath = join(cwd, 'ROADMAP.md')
1360
+ const roadmapPath = resolveRoadmapPath(cwd)
1351
1361
 
1352
1362
  if (existsSync(roadmapPath)) {
1353
1363
  // Show cwd roadmap
@@ -2423,7 +2433,11 @@ if (cmd === 'build') {
2423
2433
  } = await import('../lib/ideabox.js')
2424
2434
 
2425
2435
  const ibRelPath = getIdeaboxRelPath(ibCwd)
2426
- const ibFullPath = join(ibCwd, ibRelPath)
2436
+ // ibFullPath is used for direct file ops (existsSync/mkdirSync/writeFileSync/
2437
+ // display); resolve it absolute-safe. ibRelPath stays relative because the
2438
+ // lib readIdeabox/writeIdeabox readers re-join it under ibCwd.
2439
+ const { resolveIdeaboxPath: _resolveIdeaboxPathCli } = await import('../lib/project-paths.js')
2440
+ const ibFullPath = _resolveIdeaboxPathCli(ibCwd)
2427
2441
 
2428
2442
  if (!ibSubcmd || ibSubcmd === '--help' || ibSubcmd === '-h') {
2429
2443
  console.log('Usage: compose ideabox <subcommand>')
@@ -2541,9 +2555,10 @@ if (cmd === 'build') {
2541
2555
  resolvedCode = `IDEA-${idea.num}-${slug}`.toUpperCase()
2542
2556
  }
2543
2557
 
2544
- // Create feature folder if missing — respect paths.features from compose.json
2545
- const featuresRel = ibConfig.paths?.features || 'docs/features'
2546
- const featuresDir = join(ibCwd, featuresRel, resolvedCode)
2558
+ // Create feature folder if missing — respect paths.features (may be
2559
+ // relocated outside ibCwd COMP-PATHS-EXTERNAL; resolve absolute, no re-root)
2560
+ const featuresBase = resolveFeaturesPathFromConfig(ibCwd, ibConfig)
2561
+ const featuresDir = join(featuresBase, resolvedCode)
2547
2562
  if (!existsSync(featuresDir)) {
2548
2563
  // COMP-MCP-VALIDATE-1: route through the validated writer (schema-guarded)
2549
2564
  // instead of a raw writeFileSync.
@@ -2554,8 +2569,8 @@ if (cmd === 'build') {
2554
2569
  status: 'PLANNED',
2555
2570
  promotedFrom: ideaId,
2556
2571
  createdAt: new Date().toISOString(),
2557
- }, featuresRel)
2558
- console.log(`Created feature folder: ${featuresRel}/${resolvedCode}/`)
2572
+ }, featuresBase)
2573
+ console.log(`Created feature folder: ${join(featuresBase, resolvedCode)}/`)
2559
2574
  }
2560
2575
 
2561
2576
  _promoteIdea(parsed, ideaId, resolvedCode)