@smartmemory/compose 0.2.36-beta → 0.2.38-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 (60) hide show
  1. package/dist/assets/App-BD4lfyhF.js +686 -0
  2. package/dist/assets/{arc-DIXitrAQ.js → arc-fd_r6IIl.js} +1 -1
  3. package/dist/assets/{architectureDiagram-3BPJPVTR-Cj7dBJg7.js → architectureDiagram-3BPJPVTR-UehcfvE8.js} +1 -1
  4. package/dist/assets/{blockDiagram-GPEHLZMM-Cl9S3jDb.js → blockDiagram-GPEHLZMM-Dm-THFZ6.js} +1 -1
  5. package/dist/assets/{c4Diagram-AAUBKEIU-BhXknY2V.js → c4Diagram-AAUBKEIU-CIZ7QDGR.js} +1 -1
  6. package/dist/assets/channel-C0cFeemU.js +1 -0
  7. package/dist/assets/{chunk-2J33WTMH-D9br4z7_.js → chunk-2J33WTMH-COBZ5eyU.js} +1 -1
  8. package/dist/assets/{chunk-4BX2VUAB-BUm--OlR.js → chunk-4BX2VUAB-w3bqdoNF.js} +1 -1
  9. package/dist/assets/{chunk-55IACEB6-BPBvBDq8.js → chunk-55IACEB6-D18v8dR4.js} +1 -1
  10. package/dist/assets/{chunk-727SXJPM-D-k0AVv9.js → chunk-727SXJPM-2MAwFz_9.js} +1 -1
  11. package/dist/assets/{chunk-AQP2D5EJ-DbrnuPhd.js → chunk-AQP2D5EJ-Dp_jdVPB.js} +1 -1
  12. package/dist/assets/{chunk-FMBD7UC4-CArhG5bz.js → chunk-FMBD7UC4-mPSIpSeS.js} +1 -1
  13. package/dist/assets/{chunk-ND2GUHAM-BMqJF8Yq.js → chunk-ND2GUHAM-gkRIeuOg.js} +1 -1
  14. package/dist/assets/{chunk-QZHKN3VN-xEVO-BnU.js → chunk-QZHKN3VN-DJ7h7c2i.js} +1 -1
  15. package/dist/assets/classDiagram-4FO5ZUOK-7kNnlTD1.js +1 -0
  16. package/dist/assets/classDiagram-v2-Q7XG4LA2-7kNnlTD1.js +1 -0
  17. package/dist/assets/{cose-bilkent-S5V4N54A-D8YuuIpy.js → cose-bilkent-S5V4N54A-BC5rkVLI.js} +1 -1
  18. package/dist/assets/{dagre-BM42HDAG-DAFO7F2u.js → dagre-BM42HDAG-DBwRZbPz.js} +1 -1
  19. package/dist/assets/{diagram-2AECGRRQ-BwnnQC9d.js → diagram-2AECGRRQ-CmljsTYt.js} +1 -1
  20. package/dist/assets/{diagram-5GNKFQAL-DBEb2BhO.js → diagram-5GNKFQAL-Pcdh-Hev.js} +1 -1
  21. package/dist/assets/{diagram-KO2AKTUF-BMIv-hqj.js → diagram-KO2AKTUF-CrEqfa_s.js} +1 -1
  22. package/dist/assets/{diagram-LMA3HP47-B_BQfoht.js → diagram-LMA3HP47-pmYhkUAj.js} +1 -1
  23. package/dist/assets/{diagram-OG6HWLK6-CGX5WRJy.js → diagram-OG6HWLK6-1mWNdTnP.js} +1 -1
  24. package/dist/assets/{erDiagram-TEJ5UH35-BA3HXlzl.js → erDiagram-TEJ5UH35-BuNJLn2I.js} +1 -1
  25. package/dist/assets/{flowDiagram-I6XJVG4X-DqCc80Gc.js → flowDiagram-I6XJVG4X-D84i8zUb.js} +1 -1
  26. package/dist/assets/{ganttDiagram-6RSMTGT7-2JYlowTb.js → ganttDiagram-6RSMTGT7-DW_1tH7v.js} +1 -1
  27. package/dist/assets/{gitGraphDiagram-PVQCEYII-DeFaU-B5.js → gitGraphDiagram-PVQCEYII-Mo99IrfD.js} +1 -1
  28. package/dist/assets/{index-BUEdsF82.js → index-DfocQEE0.js} +2 -2
  29. package/dist/assets/index-vDKys15R.css +1 -0
  30. package/dist/assets/{infoDiagram-5YYISTIA-Denratb4.js → infoDiagram-5YYISTIA-BJvJda4j.js} +1 -1
  31. package/dist/assets/{ishikawaDiagram-YF4QCWOH-DmYnlEGM.js → ishikawaDiagram-YF4QCWOH-Dl7ib9vb.js} +1 -1
  32. package/dist/assets/{journeyDiagram-JHISSGLW-XCrNbncG.js → journeyDiagram-JHISSGLW-DmgxLRyA.js} +1 -1
  33. package/dist/assets/{kanban-definition-UN3LZRKU-tdCgL_BJ.js → kanban-definition-UN3LZRKU-DV6cN2Fc.js} +1 -1
  34. package/dist/assets/{linear-CQCcdMrA.js → linear-ChPnBFTg.js} +1 -1
  35. package/dist/assets/{mindmap-definition-RKZ34NQL-DtZJzpjH.js → mindmap-definition-RKZ34NQL-C0dgdrrD.js} +1 -1
  36. package/dist/assets/{pieDiagram-4H26LBE5-BFeercFA.js → pieDiagram-4H26LBE5-N-HzAPPi.js} +1 -1
  37. package/dist/assets/{quadrantDiagram-W4KKPZXB-BCX6XEvx.js → quadrantDiagram-W4KKPZXB-YEX6PyFG.js} +1 -1
  38. package/dist/assets/{requirementDiagram-4Y6WPE33-Cbby1ELs.js → requirementDiagram-4Y6WPE33-CCpgQqwO.js} +1 -1
  39. package/dist/assets/{sankeyDiagram-5OEKKPKP-CoGrYNGu.js → sankeyDiagram-5OEKKPKP-BSUvtggj.js} +1 -1
  40. package/dist/assets/{sequenceDiagram-3UESZ5HK-Ppn3RRuA.js → sequenceDiagram-3UESZ5HK-Dh8UHRBI.js} +1 -1
  41. package/dist/assets/{stateDiagram-AJRCARHV-z3isZwb4.js → stateDiagram-AJRCARHV-DKvZ4fLX.js} +1 -1
  42. package/dist/assets/stateDiagram-v2-BHNVJYJU-DF_adEfb.js +1 -0
  43. package/dist/assets/{timeline-definition-PNZ67QCA-MzpbvgHe.js → timeline-definition-PNZ67QCA-qunNDnlH.js} +1 -1
  44. package/dist/assets/{vennDiagram-CIIHVFJN-Bsvlh8Xw.js → vennDiagram-CIIHVFJN-D5a-gmIU.js} +1 -1
  45. package/dist/assets/{wardley-L42UT6IY-VWT3qdBy.js → wardley-L42UT6IY-akIUfw-F.js} +1 -1
  46. package/dist/assets/{wardleyDiagram-YWT4CUSO-DhsQvXBN.js → wardleyDiagram-YWT4CUSO-R1zmVC27.js} +1 -1
  47. package/dist/assets/{xychartDiagram-2RQKCTM6-DvmK5-UN.js → xychartDiagram-2RQKCTM6-Do2YVGeZ.js} +1 -1
  48. package/dist/index.html +2 -2
  49. package/lib/build-history.js +62 -0
  50. package/lib/build.js +27 -0
  51. package/lib/discover-workspaces.js +28 -5
  52. package/lib/resolve-workspace.js +50 -3
  53. package/package.json +1 -1
  54. package/server/build-routes.js +14 -0
  55. package/dist/assets/App-CpdZk3aa.js +0 -681
  56. package/dist/assets/channel-llllBK4h.js +0 -1
  57. package/dist/assets/classDiagram-4FO5ZUOK-BEiB5jyR.js +0 -1
  58. package/dist/assets/classDiagram-v2-Q7XG4LA2-BEiB5jyR.js +0 -1
  59. package/dist/assets/index-jqUffYBL.css +0 -1
  60. package/dist/assets/stateDiagram-v2-BHNVJYJU-CU-EnGpI.js +0 -1
@@ -5,7 +5,9 @@
5
5
  * 1. explicit hint.workspaceId (cheap upward walk first; falls back to discovery)
6
6
  * 2. COMPOSE_TARGET env (absolute path bypasses discovery; id routes through it)
7
7
  * 3. hint.getBinding() (MCP binding)
8
- * 4. discovery (auto-pick when exactly one candidate; throws otherwise)
8
+ * 4. discovery (auto-pick when exactly one candidate; throws otherwise)
9
+ * degrades to the nearest-enclosing workspace if the subtree is too broad
10
+ * to enumerate within the visit bound.
9
11
  *
10
12
  * Throws structured errors with `.code`: WorkspaceUnknown, WorkspaceAmbiguous,
11
13
  * WorkspaceIdCollision, WorkspaceUnset. The CLI's dieOnWorkspaceError consumes them.
@@ -13,6 +15,14 @@
13
15
  * Design intent: explicit-flag path uses findWorkspaceById (cheap upward walk)
14
16
  * BEFORE invoking discoverWorkspaces — this lets users escape WorkspaceDiscoveryTooBroad
15
17
  * by passing --workspace=<ancestor-id>. A descendant id still routes through discovery.
18
+ *
19
+ * The no-hint path mirrors that instinct only when the descendant scan can't
20
+ * enumerate the subtree (WorkspaceDiscoveryTooBroad): rather than failing, it
21
+ * falls back to the nearest enclosing `.compose` ancestor (upward walk), so
22
+ * running from a large workspace root resolves instead of dying. A tractable
23
+ * tree is still enumerated in full — genuine nested-workspace ambiguity (a
24
+ * parent workspace with a child below it) deliberately surfaces and forces an
25
+ * explicit --workspace.
16
26
  */
17
27
  import path from 'node:path';
18
28
  import fs from 'node:fs';
@@ -96,8 +106,26 @@ export function resolveWorkspace(hint = {}) {
96
106
  }
97
107
  }
98
108
 
99
- // 4. Discovery — collisions matter because we're auto-picking.
100
- const { candidates } = discoverWorkspaces(cwd);
109
+ // 4. Discovery — fan out under the anchor; collisions/ambiguity matter
110
+ // because we're auto-picking. A normal tree enumerates fine, so genuine
111
+ // nested-workspace ambiguity (e.g. a parent workspace with a child below)
112
+ // still surfaces as WorkspaceAmbiguous and forces an explicit --workspace.
113
+ let candidates;
114
+ try {
115
+ ({ candidates } = discoverWorkspaces(cwd));
116
+ } catch (err) {
117
+ // The subtree was too large to enumerate within the visit bound. That cap
118
+ // is a cost guard, not a verdict — if cwd is itself inside a workspace, the
119
+ // nearest enclosing `.compose` ancestor is the unambiguous answer, so we
120
+ // degrade to it instead of failing (best-effort, same philosophy as the
121
+ // scan silently skipping EACCES subtrees). Only when cwd is inside NO
122
+ // workspace must the caller disambiguate explicitly — then we rethrow.
123
+ if (err.code === 'WorkspaceDiscoveryTooBroad') {
124
+ const enclosing = findEnclosingWorkspace(cwd);
125
+ if (enclosing) return { ...deriveId({ root: enclosing }), source: 'discovery' };
126
+ }
127
+ throw err;
128
+ }
101
129
  detectCollisions(candidates);
102
130
  if (candidates.length === 0) throw new WorkspaceUnset();
103
131
  if (candidates.length === 1) return { ...candidates[0], source: 'discovery' };
@@ -124,6 +152,25 @@ function findWorkspaceById(startDir, targetId) {
124
152
  }
125
153
  }
126
154
 
155
+ /**
156
+ * Cheap upward-only lookup: walk ancestors from startDir and return the first
157
+ * directory containing a `.compose/` marker, or null if none exists before the
158
+ * filesystem root. This is the no-hint "nearest enclosing workspace" resolver —
159
+ * identical walk to findWorkspaceById but id-agnostic (returns the closest
160
+ * workspace regardless of its derived id).
161
+ */
162
+ function findEnclosingWorkspace(startDir) {
163
+ let dir = path.resolve(startDir);
164
+ const { root } = path.parse(dir);
165
+ while (true) {
166
+ if (fs.existsSync(path.join(dir, '.compose'))) return dir;
167
+ if (dir === root) return null;
168
+ const parent = path.dirname(dir);
169
+ if (parent === dir) return null;
170
+ dir = parent;
171
+ }
172
+ }
173
+
127
174
  function resolveByIdScopedCollisionCheck(id, candidates, source) {
128
175
  const matching = candidates.filter((c) => c.id === id);
129
176
  if (matching.length === 0) throw new WorkspaceUnknown(id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartmemory/compose",
3
- "version": "0.2.36-beta",
3
+ "version": "0.2.38-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",
@@ -16,12 +16,26 @@
16
16
  import { runBuild as defaultRunBuild, abortBuild as defaultAbortBuild } from '../lib/build.js';
17
17
  import { requireSensitiveToken } from './security.js';
18
18
  import { getDataDir as defaultGetDataDir } from './project-root.js';
19
+ import { readBuildHistory } from '../lib/build-history.js';
19
20
 
20
21
  export function attachBuildRoutes(app, deps = {}) {
21
22
  const runBuild = deps.runBuild || defaultRunBuild;
22
23
  const abortBuild = deps.abortBuild || defaultAbortBuild;
23
24
  const getDataDir = deps.getDataDir || defaultGetDataDir;
24
25
 
26
+ // COMP-COCKPIT-3: read-only past-builds history. No sensitive token —
27
+ // mirrors GET /api/build/state (read-only, no secrets in the records).
28
+ app.get('/api/builds', (req, res) => {
29
+ try {
30
+ const raw = parseInt(req.query.limit, 10);
31
+ const limit = Number.isFinite(raw) ? Math.min(Math.max(raw, 1), 200) : 50;
32
+ const builds = readBuildHistory(getDataDir(), { limit });
33
+ res.json({ builds });
34
+ } catch (err) {
35
+ res.status(500).json({ error: err.message || String(err) });
36
+ }
37
+ });
38
+
25
39
  app.post('/api/build/start', requireSensitiveToken, async (req, res) => {
26
40
  const body = req.body || {};
27
41
  const { featureCode, mode = 'feature', description = '' } = body;