@smartmemory/compose 0.1.8-beta → 0.1.10-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.
- package/bin/compose.js +171 -39
- package/bin/git-hooks/post-commit.template +2 -1
- package/bin/git-hooks/pre-push.template +2 -1
- package/dist/assets/{_baseUniq-3jW4HAOf.js → _baseUniq-1Y6jTF8t.js} +1 -1
- package/dist/assets/{arc-DzzDimyd.js → arc-D6ZzqBFD.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-CtAgwORz.js → architectureDiagram-Q4EWVU46-Dz07OB2P.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-Bryby0c_.js → blockDiagram-DXYQGD6D-CIx_vZA9.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-C7N9RTJ8.js → c4Diagram-AHTNJAMY-oPCtldKL.js} +1 -1
- package/dist/assets/channel-BOEco5yc.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-wijkFgZY.js → chunk-4BX2VUAB-DE1mVs3B.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-zdSZGRS2.js → chunk-4TB4RGXK-BBOEH_yf.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-6zqzTZQQ.js → chunk-55IACEB6-BNnoj3te.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-frd1Vwf-.js → chunk-EDXVE4YY-BONF1eoC.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-CdkRK5Hx.js → chunk-FMBD7UC4-ij7VBSva.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-C6bMB0cf.js → chunk-OYMX7WX6-CzccIkdC.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-4vsxN3jq.js → chunk-QZHKN3VN-6U3wTZV_.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-DbNARKip.js → chunk-YZCP3GAM-B0KFbf0L.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-Z--fTQT6.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-Z--fTQT6.js +1 -0
- package/dist/assets/clone-WlHlToLE.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-BpXeV7Vj.js → cose-bilkent-S5V4N54A-CicoNwP8.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-DQLu_W8r.js → dagre-KV5264BT-CwIGE26v.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-skaOoe5A.js → diagram-5BDNPKRD-2VTTGl95.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-DezlfFH4.js → diagram-G4DWMVQ6-3Pf96ieo.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-BUu-v-wT.js → diagram-MMDJMWI5-BMJV4Wvv.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-CziQ6LPs.js → diagram-TYMM5635-DekMw47L.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-BsAyOVTI.js → erDiagram-SMLLAGMA-CoDv7HYm.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-CbYWJOLq.js → flowDiagram-DWJPFMVM-Cnh8oAOL.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-CAwgDkLl.js → ganttDiagram-T4ZO3ILL-4E_ddNnO.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-DK4RlkjO.js → gitGraphDiagram-UUTBAWPF-BezAbuh1.js} +1 -1
- package/dist/assets/{graph-orv1XHGx.js → graph-Dwh_GDZn.js} +1 -1
- package/dist/assets/{index-Ceywghsu.js → index-DHdiTAmV.js} +224 -224
- package/dist/assets/{infoDiagram-42DDH7IO-DQyA75sK.js → infoDiagram-42DDH7IO-CQG6i5uG.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-C-F_5q4k.js → ishikawaDiagram-UXIWVN3A-DU-pg-DQ.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-Bj8UIvK-.js → journeyDiagram-VCZTEJTY-D16FySlp.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-DZYr8Dp1.js → kanban-definition-6JOO6SKY-CeBu_tC8.js} +1 -1
- package/dist/assets/{layout-CBaTKjpX.js → layout-20cH9PdF.js} +1 -1
- package/dist/assets/{linear-j1sI_SiN.js → linear-BJLAYBLR.js} +1 -1
- package/dist/assets/{min-DtJISjld.js → min-DpwGyJGd.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-Bulb64RS.js → mindmap-definition-QFDTVHPH-Cs8A-hRb.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-D11keQxr.js → pieDiagram-DEJITSTG-B_3gJ-t1.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-BEcWQiEG.js → quadrantDiagram-34T5L4WZ-CWwkmlo7.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-Cbp23uDf.js → requirementDiagram-MS252O5E-B5_FnptK.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-Dae1hMc5.js → sankeyDiagram-XADWPNL6-C1V7g3pp.js} +1 -1
- package/dist/assets/{sequenceDiagram-FGHM5R23-C16abORi.js → sequenceDiagram-FGHM5R23-Cx40AcDN.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-CbEtfhbx.js → stateDiagram-FHFEXIEX-MB9EofRm.js} +1 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-B2uq4PdS.js +1 -0
- package/dist/assets/{timeline-definition-GMOUNBTQ-BV7JTNMI.js → timeline-definition-GMOUNBTQ-BVeH32Lw.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-DBZiT48j.js → vennDiagram-DHZGUBPP-COiwH6EY.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-Cc8uoiL3.js → wardley-RL74JXVD-BOOKZXAy.js} +1 -1
- package/dist/assets/{wardleyDiagram-NUSXRM2D-DEYcWGo5.js → wardleyDiagram-NUSXRM2D-Cjobr6lF.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-bFhLXv2b.js → xychartDiagram-5P7HB3ND-Bj1YVrJO.js} +1 -1
- package/dist/index.html +1 -1
- package/lib/discover-workspaces.js +109 -0
- package/lib/resolve-workspace.js +166 -0
- package/lib/vision-writer.js +7 -1
- package/package.json +1 -2
- package/server/compose-mcp-tools.js +114 -93
- package/server/compose-mcp.js +42 -0
- package/server/design-routes.js +5 -2
- package/server/index.js +5 -0
- package/server/project-root.js +4 -0
- package/server/workspace-middleware.js +120 -0
- package/server/workspace-routes.js +25 -0
- package/dist/assets/channel-DDkv7DUd.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-J6ZTeCbW.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-J6ZTeCbW.js +0 -1
- package/dist/assets/clone-5MVZ89iV.js +0 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-CyY84hEA.js +0 -1
package/server/compose-mcp.js
CHANGED
|
@@ -59,7 +59,12 @@ import {
|
|
|
59
59
|
toolGetCompletions,
|
|
60
60
|
toolValidateFeature,
|
|
61
61
|
toolValidateProject,
|
|
62
|
+
toolSetWorkspace,
|
|
63
|
+
toolGetWorkspace,
|
|
64
|
+
_getBinding,
|
|
62
65
|
} from './compose-mcp-tools.js';
|
|
66
|
+
import { switchProject, getTargetRoot } from './project-root.js';
|
|
67
|
+
import { resolveWorkspace } from '../lib/resolve-workspace.js';
|
|
63
68
|
|
|
64
69
|
// ---------------------------------------------------------------------------
|
|
65
70
|
// Tool definitions
|
|
@@ -151,6 +156,20 @@ const TOOLS = [
|
|
|
151
156
|
required: ['featureCode'],
|
|
152
157
|
},
|
|
153
158
|
},
|
|
159
|
+
{
|
|
160
|
+
name: 'set_workspace',
|
|
161
|
+
description: 'Bind this MCP session to a workspace. Required when cwd contains multiple workspaces. Lives in process memory; lost on MCP restart.',
|
|
162
|
+
inputSchema: {
|
|
163
|
+
type: 'object',
|
|
164
|
+
required: ['workspaceId'],
|
|
165
|
+
properties: { workspaceId: { type: 'string', description: 'Workspace ID (kebab-case)' } },
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: 'get_workspace',
|
|
170
|
+
description: 'Get the current MCP workspace binding plus all candidates discovered from cwd.',
|
|
171
|
+
inputSchema: { type: 'object', properties: {} },
|
|
172
|
+
},
|
|
154
173
|
{
|
|
155
174
|
name: 'get_feature_lifecycle',
|
|
156
175
|
description: 'Get the lifecycle state of a feature: current phase, phase history, artifacts, warnings.',
|
|
@@ -570,7 +589,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
570
589
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
571
590
|
const { name, arguments: args = {} } = request.params;
|
|
572
591
|
|
|
592
|
+
const WORKSPACE_EXEMPT = new Set(['set_workspace', 'get_workspace']);
|
|
593
|
+
|
|
573
594
|
try {
|
|
595
|
+
if (!WORKSPACE_EXEMPT.has(name)) {
|
|
596
|
+
const ws = resolveWorkspace({ getBinding: _getBinding });
|
|
597
|
+
if (ws.root !== getTargetRoot()) switchProject(ws.root);
|
|
598
|
+
}
|
|
574
599
|
let result;
|
|
575
600
|
switch (name) {
|
|
576
601
|
case 'get_vision_items': result = toolGetVisionItems(args); break;
|
|
@@ -579,6 +604,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
579
604
|
case 'get_blocked_items': result = toolGetBlockedItems(); break;
|
|
580
605
|
case 'get_current_session': result = await toolGetCurrentSession(args); break;
|
|
581
606
|
case 'bind_session': result = await toolBindSession(args); break;
|
|
607
|
+
case 'set_workspace': result = toolSetWorkspace(args); break;
|
|
608
|
+
case 'get_workspace': result = toolGetWorkspace(); break;
|
|
582
609
|
case 'get_feature_lifecycle': result = toolGetFeatureLifecycle(args); break;
|
|
583
610
|
case 'kill_feature': result = await toolKillFeature(args); break;
|
|
584
611
|
case 'complete_feature': result = await toolCompleteFeature(args); break;
|
|
@@ -624,6 +651,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
624
651
|
let text = err && err.code
|
|
625
652
|
? `Error [${err.code}]: ${err.message}`
|
|
626
653
|
: `Error: ${err.message}`;
|
|
654
|
+
// For workspace ambiguity, include the candidate list and the call to fix it
|
|
655
|
+
// so Claude can prompt the user without a follow-up tool call.
|
|
656
|
+
if (err && err.code === 'WorkspaceAmbiguous' && Array.isArray(err.candidates)) {
|
|
657
|
+
text += '\n\nCandidates:';
|
|
658
|
+
for (const c of err.candidates) text += `\n - ${c.id} (${c.root})`;
|
|
659
|
+
text += '\n\nNext step: call set_workspace({"workspaceId": "<id>"}) and retry.';
|
|
660
|
+
}
|
|
661
|
+
if (err && err.code === 'WorkspaceIdCollision' && Array.isArray(err.roots)) {
|
|
662
|
+
text += `\n\nworkspaceId "${err.id}" is used by multiple roots:`;
|
|
663
|
+
for (const r of err.roots) text += `\n - ${r}`;
|
|
664
|
+
text += '\n\nFix: set an explicit workspaceId in each .compose/compose.json.';
|
|
665
|
+
}
|
|
666
|
+
if (err && err.code === 'WorkspaceUnset') {
|
|
667
|
+
text += '\n\nNo .compose/ workspace was found. Run `compose init` to scaffold one.';
|
|
668
|
+
}
|
|
627
669
|
if (err && err.cause && typeof err.cause.message === 'string') {
|
|
628
670
|
text += err.cause.code
|
|
629
671
|
? `\n Caused by [${err.cause.code}]: ${err.cause.message}`
|
package/server/design-routes.js
CHANGED
|
@@ -468,15 +468,18 @@ Output ONLY the Markdown content, no code fences.`;
|
|
|
468
468
|
if (scope === 'feature' && featureCode) {
|
|
469
469
|
try {
|
|
470
470
|
const apiBase = `http://127.0.0.1:${process.env.PORT || 4001}`;
|
|
471
|
+
const wsHeaders = req.workspace?.id ? { 'X-Compose-Workspace-Id': req.workspace.id } : {};
|
|
471
472
|
// Look up the vision item for this featureCode
|
|
472
|
-
const itemsRes = await fetch(`${apiBase}/api/vision/items?keyword=${encodeURIComponent(featureCode)}
|
|
473
|
+
const itemsRes = await fetch(`${apiBase}/api/vision/items?keyword=${encodeURIComponent(featureCode)}`, {
|
|
474
|
+
headers: { ...wsHeaders },
|
|
475
|
+
});
|
|
473
476
|
const itemsData = await itemsRes.json();
|
|
474
477
|
const featureItem = itemsData.items?.find(i =>
|
|
475
478
|
i.title?.startsWith(featureCode) || i.lifecycle?.featureCode === featureCode || i.featureCode === featureCode
|
|
476
479
|
);
|
|
477
480
|
await fetch(`${apiBase}/api/vision/gates`, {
|
|
478
481
|
method: 'POST',
|
|
479
|
-
headers: { 'Content-Type': 'application/json' },
|
|
482
|
+
headers: { 'Content-Type': 'application/json', ...wsHeaders },
|
|
480
483
|
body: JSON.stringify({
|
|
481
484
|
flowId: `design-${featureCode}`,
|
|
482
485
|
stepId: 'design_gate',
|
package/server/index.js
CHANGED
|
@@ -9,6 +9,8 @@ import { VisionServer } from './vision-server.js';
|
|
|
9
9
|
import { SessionManager } from './session-manager.js';
|
|
10
10
|
import { scanFeatures, seedFeatures, scanSubPackages, seedSubPackages, seedFromRoadmapGraph } from './feature-scan.js';
|
|
11
11
|
import { attachGraphExportRoutes } from './graph-export.js';
|
|
12
|
+
import { attachWorkspaceRoutes } from './workspace-routes.js';
|
|
13
|
+
import { createWorkspaceMiddleware } from './workspace-middleware.js';
|
|
12
14
|
import { getTargetRoot, getDataDir, ensureDataDir, loadProjectConfig, resolveProjectPath, switchProject } from './project-root.js';
|
|
13
15
|
|
|
14
16
|
// Load project config and verify stratum capability matches reality
|
|
@@ -47,6 +49,9 @@ const app = express();
|
|
|
47
49
|
app.use(cors({ origin: /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/ }));
|
|
48
50
|
app.use(express.json());
|
|
49
51
|
|
|
52
|
+
attachWorkspaceRoutes(app);
|
|
53
|
+
app.use(createWorkspaceMiddleware());
|
|
54
|
+
|
|
50
55
|
app.get('/api/health', (_req, res) => res.json({ ok: true }));
|
|
51
56
|
app.get('/api/status', (_req, res) => res.json({ session: 2, phase: '0.4-brainstorm', upSince: new Date().toISOString() }));
|
|
52
57
|
|
package/server/project-root.js
CHANGED
|
@@ -48,6 +48,10 @@ export function getTargetRoot() { return _targetRoot; }
|
|
|
48
48
|
/** Data directory for Compose state. Lives in the target project. */
|
|
49
49
|
export function getDataDir() { return _dataDir; }
|
|
50
50
|
|
|
51
|
+
let _currentWorkspaceId = null;
|
|
52
|
+
export function getCurrentWorkspaceId() { return _currentWorkspaceId; }
|
|
53
|
+
export function setCurrentWorkspaceId(id) { _currentWorkspaceId = id; }
|
|
54
|
+
|
|
51
55
|
// ---------------------------------------------------------------------------
|
|
52
56
|
// Switch project at runtime
|
|
53
57
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace-middleware.js — Express middleware that resolves the per-request
|
|
3
|
+
* workspace from the `X-Compose-Workspace-Id` header and attaches it as
|
|
4
|
+
* `req.workspace = { id, root, source, configPath? }`.
|
|
5
|
+
*
|
|
6
|
+
* Behavior (v1):
|
|
7
|
+
* - Exempt paths (/api/workspace, /api/project/switch, /api/health) bypass
|
|
8
|
+
* resolution entirely and get `req.workspace.source = 'exempt'`.
|
|
9
|
+
* - Header present + valid → resolveWorkspace() result, source carried through.
|
|
10
|
+
* - Header absent + soft fallback enabled → fallback to getTargetRoot() with
|
|
11
|
+
* the `X-Compose-Workspace-Fallback: true` response header. Applies to
|
|
12
|
+
* ALL methods in v1 (GET and POST alike).
|
|
13
|
+
* - Resolver errors map to HTTP via mapResolverErrorToResponse:
|
|
14
|
+
* WorkspaceUnknown → 400 { error, code, id }
|
|
15
|
+
* WorkspaceAmbiguous → 409 { error, code, candidates }
|
|
16
|
+
* WorkspaceIdCollision → 409 { error, code, roots }
|
|
17
|
+
* WorkspaceDiscoveryTooBroad → 400 { error, code }
|
|
18
|
+
* (anything else) → 500 { error: '...' }
|
|
19
|
+
*
|
|
20
|
+
* Roadmap: COMP-WORKSPACE-HTTP T3.
|
|
21
|
+
*/
|
|
22
|
+
import { getTargetRoot } from './project-root.js';
|
|
23
|
+
import {
|
|
24
|
+
resolveWorkspace,
|
|
25
|
+
WorkspaceUnknown,
|
|
26
|
+
WorkspaceAmbiguous,
|
|
27
|
+
WorkspaceIdCollision,
|
|
28
|
+
} from '../lib/resolve-workspace.js';
|
|
29
|
+
|
|
30
|
+
const EXEMPT_PATHS = new Set([
|
|
31
|
+
'/api/workspace',
|
|
32
|
+
'/api/project/switch',
|
|
33
|
+
'/api/health',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Factory for the Express middleware.
|
|
38
|
+
*
|
|
39
|
+
* @param {object} [opts]
|
|
40
|
+
* @param {boolean} [opts.allowGetFallback=true] — when true, requests without
|
|
41
|
+
* the workspace header soft-fallback to the target root with a hint header.
|
|
42
|
+
* When false, missing header surfaces as a WorkspaceUnknown(null) → 400.
|
|
43
|
+
*/
|
|
44
|
+
export function createWorkspaceMiddleware({ allowGetFallback = true } = {}) {
|
|
45
|
+
return function workspaceMiddleware(req, res, next) {
|
|
46
|
+
if (EXEMPT_PATHS.has(req.path)) {
|
|
47
|
+
req.workspace = { id: null, root: getTargetRoot(), source: 'exempt' };
|
|
48
|
+
return next();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const headerId = req.headers['x-compose-workspace-id'];
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
if (!headerId) {
|
|
55
|
+
if (allowGetFallback) {
|
|
56
|
+
req.workspace = { id: null, root: getTargetRoot(), source: 'fallback' };
|
|
57
|
+
res.setHeader('X-Compose-Workspace-Fallback', 'true');
|
|
58
|
+
return next();
|
|
59
|
+
}
|
|
60
|
+
// Hard-fail mode: missing header is treated as an unknown id.
|
|
61
|
+
throw new WorkspaceUnknown(null);
|
|
62
|
+
}
|
|
63
|
+
const resolved = resolveWorkspace({
|
|
64
|
+
workspaceId: headerId,
|
|
65
|
+
cwd: getTargetRoot(),
|
|
66
|
+
});
|
|
67
|
+
req.workspace = resolved;
|
|
68
|
+
next();
|
|
69
|
+
} catch (err) {
|
|
70
|
+
mapResolverErrorToResponse(err, res, next);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Translate a resolver error into a JSON HTTP response.
|
|
77
|
+
*
|
|
78
|
+
* @param {Error} err
|
|
79
|
+
* @param {import('express').Response} res
|
|
80
|
+
* @param {import('express').NextFunction} [next] — optional; if provided,
|
|
81
|
+
* truly unknown errors are forwarded to it instead of generating a 500.
|
|
82
|
+
*/
|
|
83
|
+
export function mapResolverErrorToResponse(err, res, next) {
|
|
84
|
+
if (err instanceof WorkspaceUnknown || err?.code === 'WorkspaceUnknown') {
|
|
85
|
+
return res.status(400).json({
|
|
86
|
+
error: err.message,
|
|
87
|
+
code: 'WorkspaceUnknown',
|
|
88
|
+
id: err.id ?? null,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (err instanceof WorkspaceAmbiguous || err?.code === 'WorkspaceAmbiguous') {
|
|
92
|
+
return res.status(409).json({
|
|
93
|
+
error: err.message,
|
|
94
|
+
code: 'WorkspaceAmbiguous',
|
|
95
|
+
candidates: err.candidates ?? [],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (err instanceof WorkspaceIdCollision || err?.code === 'WorkspaceIdCollision') {
|
|
99
|
+
return res.status(409).json({
|
|
100
|
+
error: err.message,
|
|
101
|
+
code: 'WorkspaceIdCollision',
|
|
102
|
+
roots: err.roots ?? [],
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (err?.code === 'WorkspaceDiscoveryTooBroad') {
|
|
106
|
+
return res.status(400).json({
|
|
107
|
+
error: err.message,
|
|
108
|
+
code: 'WorkspaceDiscoveryTooBroad',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (typeof next === 'function') {
|
|
112
|
+
return next(err);
|
|
113
|
+
}
|
|
114
|
+
return res.status(500).json({
|
|
115
|
+
error: err?.message || 'Internal workspace resolver error',
|
|
116
|
+
code: err?.code || 'WorkspaceResolverInternalError',
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { EXEMPT_PATHS };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace-routes.js — boot-deterministic workspace identity endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Mounts GET /api/workspace, returning the workspace resolved at boot time.
|
|
5
|
+
* No descendant discovery, no ambiguity check, no resolveWorkspace() call —
|
|
6
|
+
* this is the bootstrap endpoint the frontend hits BEFORE it has a workspace
|
|
7
|
+
* id to send (per design SD-2 of COMP-WORKSPACE-HTTP).
|
|
8
|
+
*
|
|
9
|
+
* Response shape: { id, root, source: 'boot' }
|
|
10
|
+
* - id — string, derived via deriveId({ root }).id
|
|
11
|
+
* - root — absolute path of the boot target
|
|
12
|
+
* - source — always 'boot' for this endpoint
|
|
13
|
+
*/
|
|
14
|
+
import { getTargetRoot } from './project-root.js';
|
|
15
|
+
import { deriveId } from '../lib/discover-workspaces.js';
|
|
16
|
+
|
|
17
|
+
export function attachWorkspaceRoutes(app) {
|
|
18
|
+
app.get('/api/workspace', (req, res) => {
|
|
19
|
+
const root = getTargetRoot();
|
|
20
|
+
// deriveId returns { id, root, configPath } — destructure the id only.
|
|
21
|
+
// The route deliberately does NOT leak configPath to the client.
|
|
22
|
+
const { id } = deriveId({ root });
|
|
23
|
+
res.json({ id, root, source: 'boot' });
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{aq as o,ar as n}from"./index-Ceywghsu.js";const t=(r,a)=>o.lang.round(n.parse(r)[a]);export{t as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-zdSZGRS2.js";import{_ as i}from"./index-Ceywghsu.js";import"./chunk-FMBD7UC4-CdkRK5Hx.js";import"./chunk-YZCP3GAM-DbNARKip.js";import"./chunk-55IACEB6-6zqzTZQQ.js";import"./chunk-EDXVE4YY-frd1Vwf-.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-zdSZGRS2.js";import{_ as i}from"./index-Ceywghsu.js";import"./chunk-FMBD7UC4-CdkRK5Hx.js";import"./chunk-YZCP3GAM-DbNARKip.js";import"./chunk-55IACEB6-6zqzTZQQ.js";import"./chunk-EDXVE4YY-frd1Vwf-.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as r}from"./graph-orv1XHGx.js";var e=4;function a(o){return r(o,e)}export{a as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as t,b as r,a,S as s}from"./chunk-OYMX7WX6-C6bMB0cf.js";import{_ as i}from"./index-Ceywghsu.js";import"./chunk-55IACEB6-6zqzTZQQ.js";import"./chunk-EDXVE4YY-frd1Vwf-.js";var l={parser:a,get db(){return new s(2)},renderer:r,styles:t,init:i(e=>{e.state||(e.state={}),e.state.arrowMarkerAbsolute=e.arrowMarkerAbsolute},"init")};export{l as diagram};
|