@smartmemory/compose 0.2.50-beta → 0.2.51-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/.claude/skills/compose/SKILL.md +24 -1
- package/.claude/skills/compose/references/hermes-tools.md +80 -0
- package/README.md +1 -1
- package/bin/compose.js +310 -52
- package/dist/assets/App-CT0vXPgd.js +724 -0
- package/dist/assets/_baseUniq-CsOHc_iS.js +1 -0
- package/dist/assets/{arc-DeHak63Z.js → arc-BXht3LyE.js} +1 -1
- package/dist/assets/architectureDiagram-Q4EWVU46-BV1r86-w.js +36 -0
- package/dist/assets/blockDiagram-DXYQGD6D-BgcMJjAR.js +132 -0
- package/dist/assets/{browser-DW2JlJCC.js → browser-CnKiSnlr.js} +6 -6
- package/dist/assets/{c4Diagram-AAUBKEIU-BsFJmPuS.js → c4Diagram-AHTNJAMY-nBIRLJTv.js} +1 -1
- package/dist/assets/channel-Dd4XaiYv.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-XO4S2_89.js → chunk-4BX2VUAB-CNmGyhrp.js} +1 -1
- package/dist/assets/chunk-4TB4RGXK-MLT7I7w4.js +206 -0
- package/dist/assets/{chunk-55IACEB6-CtFSLInj.js → chunk-55IACEB6-D8KuKVLa.js} +1 -1
- package/dist/assets/{chunk-2J33WTMH-AEu6HIoY.js → chunk-EDXVE4YY-TPlt1bS2.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-BMGd_Y9a.js → chunk-FMBD7UC4-tYY8xcjr.js} +1 -1
- package/dist/assets/chunk-OYMX7WX6-yBPwT1AT.js +231 -0
- package/dist/assets/{chunk-QZHKN3VN-DHhUJ8RK.js → chunk-QZHKN3VN-B4Wfybww.js} +1 -1
- package/dist/assets/{chunk-ND2GUHAM-BlrOECEr.js → chunk-YZCP3GAM-DE6_5aqh.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-DshSQDF9.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-DshSQDF9.js +1 -0
- package/dist/assets/clone-CBsbNGAa.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-C3M0mZqk.js → cose-bilkent-S5V4N54A-DzzRyJtB.js} +1 -1
- package/dist/assets/dagre-KV5264BT-CTcTVGdU.js +4 -0
- package/dist/assets/diagram-5BDNPKRD-qR6mc8kJ.js +10 -0
- package/dist/assets/diagram-G4DWMVQ6-CUcGXyNb.js +24 -0
- package/dist/assets/diagram-MMDJMWI5-B68cPonH.js +43 -0
- package/dist/assets/diagram-TYMM5635-q8Id8eFG.js +24 -0
- package/dist/assets/{erDiagram-TEJ5UH35-AMDitV0b.js → erDiagram-SMLLAGMA-CtxJi57K.js} +1 -1
- package/dist/assets/{flowDiagram-I6XJVG4X-C0t2ZGQv.js → flowDiagram-DWJPFMVM-BzzO4JYU.js} +1 -1
- package/dist/assets/ganttDiagram-T4ZO3ILL-Dn0wIyhR.js +292 -0
- package/dist/assets/gitGraphDiagram-UUTBAWPF-tnNFXfMM.js +106 -0
- package/dist/assets/graph-DZe55uk8.js +331 -0
- package/dist/assets/graph-Tq_bs_r0.js +1 -0
- package/dist/assets/index-8UhRLbGq.js +123 -0
- package/dist/assets/index-CRqB9els.css +1 -0
- package/dist/assets/infoDiagram-42DDH7IO-BXLvLeS0.js +2 -0
- package/dist/assets/{ishikawaDiagram-YF4QCWOH-CCBwgjFs.js → ishikawaDiagram-UXIWVN3A-DWx-7BBy.js} +5 -5
- package/dist/assets/{journeyDiagram-JHISSGLW-zUJN38EU.js → journeyDiagram-VCZTEJTY-C42hXNha.js} +1 -1
- package/dist/assets/{kanban-definition-UN3LZRKU-BNxWi-8J.js → kanban-definition-6JOO6SKY-CEq930ew.js} +1 -1
- package/dist/assets/katex-DkKDou_j.js +257 -0
- package/dist/assets/layout-qtUgN9BC.js +1 -0
- package/dist/assets/{linear-CRH9b4g7.js → linear-D158F7OT.js} +1 -1
- package/dist/assets/min-hESxN-c0.js +1 -0
- package/dist/assets/{mindmap-definition-RKZ34NQL-DolYwq7Y.js → mindmap-definition-QFDTVHPH-d9SSh2nG.js} +7 -7
- package/dist/assets/mobile-1gVCT0OK.css +1 -0
- package/dist/assets/mobile-Chw8RWyH.js +17 -0
- package/dist/assets/pieDiagram-DEJITSTG-gglmeMav.js +30 -0
- package/dist/assets/quadrantDiagram-34T5L4WZ-CqFC_htU.js +7 -0
- package/dist/assets/{requirementDiagram-4Y6WPE33-DsXZ05jo.js → requirementDiagram-MS252O5E-B1ZFIotK.js} +1 -1
- package/dist/assets/sankeyDiagram-XADWPNL6-BvItvZt5.js +10 -0
- package/dist/assets/sequenceDiagram-FGHM5R23-CAIn5Z3U.js +157 -0
- package/dist/assets/stateDiagram-FHFEXIEX-CyJrGzib.js +1 -0
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-DprhF_Ho.js +1 -0
- package/dist/assets/{timeline-definition-PNZ67QCA-Bvnhw58e.js → timeline-definition-GMOUNBTQ-k_0vJQAK.js} +1 -1
- package/dist/assets/{vennDiagram-CIIHVFJN-5WnyjZqf.js → vennDiagram-DHZGUBPP-TZAW60b0.js} +4 -4
- package/dist/assets/wardley-RL74JXVD-DzQEoG6X.js +162 -0
- package/dist/assets/wardleyDiagram-NUSXRM2D-BAoVVIjZ.js +20 -0
- package/dist/assets/{xychartDiagram-2RQKCTM6-BCShes6B.js → xychartDiagram-5P7HB3ND-CynkZcUb.js} +1 -1
- package/dist/index.html +4 -4
- package/lib/build.js +272 -33
- package/lib/codex-preflight.js +151 -0
- package/lib/completion-writer.js +21 -1
- package/lib/feature-validator.js +5 -1
- package/lib/hooks-status.js +135 -0
- package/lib/install-agent-defs.js +22 -0
- package/lib/migrate-anon.js +277 -0
- package/lib/roadmap-parser.js +1 -1
- package/lib/test-bootstrap.js +165 -2
- package/lib/vocabulary-inject.js +103 -0
- package/package.json +2 -1
- package/pipelines/build-quick.stratum.yaml +433 -0
- package/pipelines/build.stratum.yaml +60 -3
- package/scripts/watch-server.sh +32 -0
- package/server/build-routes.js +89 -9
- package/server/build-stream-bridge.js +12 -0
- package/server/compose-mcp-tools.js +73 -1
- package/server/compose-mcp.js +27 -0
- package/server/feature-scaffold-routes.js +82 -0
- package/server/health-routes.js +261 -0
- package/server/qa-scope-routes.js +96 -0
- package/server/validate-routes.js +70 -0
- package/server/vision-routes.js +29 -0
- package/server/vision-server.js +21 -0
- package/dist/assets/App-Bxyif1yv.js +0 -706
- package/dist/assets/architectureDiagram-3BPJPVTR-C5Nkyl9y.js +0 -36
- package/dist/assets/blockDiagram-GPEHLZMM-BilnUBG2.js +0 -132
- package/dist/assets/channel-ZgbQ1k0u.js +0 -1
- package/dist/assets/chunk-727SXJPM-CZeBRpM9.js +0 -206
- package/dist/assets/chunk-AQP2D5EJ-_vmxcBc4.js +0 -231
- package/dist/assets/classDiagram-4FO5ZUOK-KXxOorUx.js +0 -1
- package/dist/assets/classDiagram-v2-Q7XG4LA2-KXxOorUx.js +0 -1
- package/dist/assets/dagre-BM42HDAG-DJlm4fEk.js +0 -4
- package/dist/assets/diagram-2AECGRRQ-BmcONQG5.js +0 -43
- package/dist/assets/diagram-5GNKFQAL-5JbWGIwd.js +0 -10
- package/dist/assets/diagram-KO2AKTUF-DAnIvyI0.js +0 -3
- package/dist/assets/diagram-LMA3HP47-Bmh7tvmI.js +0 -24
- package/dist/assets/diagram-OG6HWLK6-hnHVMNnk.js +0 -24
- package/dist/assets/ganttDiagram-6RSMTGT7-BPlM-BEN.js +0 -292
- package/dist/assets/gitGraphDiagram-PVQCEYII-Lv_YTxnb.js +0 -106
- package/dist/assets/graph-BBXaecIU.js +0 -331
- package/dist/assets/graph-CAnANduQ.js +0 -1
- package/dist/assets/index-BwLfbbOu.css +0 -1
- package/dist/assets/index-COq21Zym.js +0 -119
- package/dist/assets/infoDiagram-5YYISTIA-Dul1vdUm.js +0 -2
- package/dist/assets/katex-C5jXJg4s.js +0 -257
- package/dist/assets/layout-DGIYPm2g.js +0 -1
- package/dist/assets/mobile-Cag5dHlF.css +0 -1
- package/dist/assets/mobile-DwmxS_O4.js +0 -17
- package/dist/assets/pieDiagram-4H26LBE5-oxNfr2TX.js +0 -30
- package/dist/assets/quadrantDiagram-W4KKPZXB-BmZCvD-z.js +0 -7
- package/dist/assets/sankeyDiagram-5OEKKPKP-DsnYaawP.js +0 -40
- package/dist/assets/sequenceDiagram-3UESZ5HK-Dt5mu3g8.js +0 -162
- package/dist/assets/stateDiagram-AJRCARHV-BFR5ZINQ.js +0 -1
- package/dist/assets/stateDiagram-v2-BHNVJYJU-BDrQD8fR.js +0 -1
- package/dist/assets/wardley-L42UT6IY-CTxW4xow.js +0 -173
- package/dist/assets/wardleyDiagram-YWT4CUSO-K8Y1EOvb.js +0 -78
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* qa-scope-routes.js — Read-only QA-scope REST API (COMP-PARITY-10).
|
|
3
|
+
*
|
|
4
|
+
* Route:
|
|
5
|
+
* GET /api/qa-scope?featureCode=<CODE> — surfaces `compose qa-scope <CODE>`
|
|
6
|
+
* (diff-to-route mapping from COMP-QA) as structured JSON for the cockpit's
|
|
7
|
+
* QA Scope view. Maps the feature's recorded filesChanged → affected /
|
|
8
|
+
* adjacent routes via lib/qa-scoping.js. Read-only, no side effects.
|
|
9
|
+
*
|
|
10
|
+
* Not auth-gated (mirrors GET /api/environment-health): it reads only
|
|
11
|
+
* feature.json + heuristic route mapping, no host paths leaked, no mutation.
|
|
12
|
+
*
|
|
13
|
+
* Degrade-never-fail: a bad feature code or unreadable feature.json returns a
|
|
14
|
+
* structured { found:false } / empty result, never a 500.
|
|
15
|
+
*
|
|
16
|
+
* Reuses (no logic fork):
|
|
17
|
+
* - lib/feature-json.js — readFeature(cwd, code)
|
|
18
|
+
* - lib/qa-scoping.js — mapFilesToRoutes(filesChanged,{cwd}), classifyRoutes(routes,[])
|
|
19
|
+
*/
|
|
20
|
+
import { readFeature as defaultReadFeature } from '../lib/feature-json.js';
|
|
21
|
+
import {
|
|
22
|
+
mapFilesToRoutes as defaultMapFilesToRoutes,
|
|
23
|
+
classifyRoutes as defaultClassifyRoutes,
|
|
24
|
+
} from '../lib/qa-scoping.js';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {import('express').Express} app
|
|
28
|
+
* @param {object} [deps]
|
|
29
|
+
* @param {Function} [deps.readFeature] — (cwd, code) => FeatureJson|null
|
|
30
|
+
* @param {Function} [deps.mapFilesToRoutes] — (filesChanged, {cwd}) => {affectedRoutes,unmappedFiles,framework,docsOnly}
|
|
31
|
+
* @param {Function} [deps.classifyRoutes] — (routes, allKnown) => {affected,adjacent}
|
|
32
|
+
*/
|
|
33
|
+
export function attachQaScopeRoutes(app, {
|
|
34
|
+
readFeature = defaultReadFeature,
|
|
35
|
+
mapFilesToRoutes = defaultMapFilesToRoutes,
|
|
36
|
+
classifyRoutes = defaultClassifyRoutes,
|
|
37
|
+
} = {}) {
|
|
38
|
+
app.get('/api/qa-scope', (req, res) => {
|
|
39
|
+
const featureCode = (req.query.featureCode || '').toString().trim();
|
|
40
|
+
if (!featureCode) {
|
|
41
|
+
return res.json({ found: false, error: 'featureCode required' });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const root = req.workspace?.root;
|
|
45
|
+
if (!root) {
|
|
46
|
+
return res.json({ found: false, error: 'no workspace root', featureCode });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let feature;
|
|
50
|
+
try {
|
|
51
|
+
feature = readFeature(root, featureCode);
|
|
52
|
+
} catch {
|
|
53
|
+
feature = null;
|
|
54
|
+
}
|
|
55
|
+
if (!feature) {
|
|
56
|
+
return res.json({ found: false, featureCode });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const filesChanged = feature.filesChanged ?? [];
|
|
60
|
+
if (filesChanged.length === 0) {
|
|
61
|
+
// Mirror the CLI's empty-diff guidance (bin/compose.js:2716-2719).
|
|
62
|
+
return res.json({
|
|
63
|
+
found: true,
|
|
64
|
+
featureCode,
|
|
65
|
+
filesChanged: [],
|
|
66
|
+
framework: 'unknown',
|
|
67
|
+
docsOnly: false,
|
|
68
|
+
affected: [],
|
|
69
|
+
adjacent: [],
|
|
70
|
+
unmappedFiles: [],
|
|
71
|
+
emptyDiff: true,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Same pipeline as the CLI (bin/compose.js:2722-2724); allKnown=[] (v1: no registry).
|
|
76
|
+
let result, classified;
|
|
77
|
+
try {
|
|
78
|
+
result = mapFilesToRoutes(filesChanged, { cwd: root });
|
|
79
|
+
classified = classifyRoutes(result.affectedRoutes, []);
|
|
80
|
+
} catch (e) {
|
|
81
|
+
return res.json({ found: true, featureCode, error: e?.message || 'qa-scope failed' });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
res.json({
|
|
85
|
+
found: true,
|
|
86
|
+
featureCode,
|
|
87
|
+
filesChanged,
|
|
88
|
+
framework: result.framework,
|
|
89
|
+
docsOnly: result.docsOnly,
|
|
90
|
+
affected: classified.affected,
|
|
91
|
+
adjacent: classified.adjacent,
|
|
92
|
+
unmappedFiles: result.unmappedFiles,
|
|
93
|
+
emptyDiff: false,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate-routes.js — Read-only cross-artifact validation REST API (COMP-PARITY-6).
|
|
3
|
+
*
|
|
4
|
+
* Route:
|
|
5
|
+
* GET /api/validate?scope=feature|project&featureCode=<CODE>
|
|
6
|
+
* Surfaces `compose validate` (lib/feature-validator.js validateFeature/
|
|
7
|
+
* validateProject) as structured JSON for the cockpit Validate view.
|
|
8
|
+
* Read-only; local-only (no network xref resolution); degrades, never 500s.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately NOT under an auth-allowlisted prefix (mirrors health-routes.js):
|
|
11
|
+
* non-allowlisted → default-deny in remote mode, open on localhost.
|
|
12
|
+
*
|
|
13
|
+
* Reuses (no logic fork): lib/feature-validator.js validateFeature/validateProject.
|
|
14
|
+
*/
|
|
15
|
+
import {
|
|
16
|
+
validateFeature as defaultValidateFeature,
|
|
17
|
+
validateProject as defaultValidateProject,
|
|
18
|
+
} from '../lib/feature-validator.js';
|
|
19
|
+
|
|
20
|
+
const SEVERITIES = ['error', 'warning', 'info'];
|
|
21
|
+
|
|
22
|
+
/** Group a findings array into { error: n, warning: n, info: n }. */
|
|
23
|
+
export function summarizeFindings(findings = []) {
|
|
24
|
+
const by = { error: 0, warning: 0, info: 0 };
|
|
25
|
+
for (const f of findings) {
|
|
26
|
+
if (by[f?.severity] !== undefined) by[f.severity] += 1;
|
|
27
|
+
}
|
|
28
|
+
return by;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {import('express').Express} app
|
|
33
|
+
* @param {object} [deps]
|
|
34
|
+
* @param {Function} [deps.validateFeature] — injectable (default: lib validator)
|
|
35
|
+
* @param {Function} [deps.validateProject] — injectable (default: lib validator)
|
|
36
|
+
*/
|
|
37
|
+
export function attachValidateRoutes(app, {
|
|
38
|
+
validateFeature = defaultValidateFeature,
|
|
39
|
+
validateProject = defaultValidateProject,
|
|
40
|
+
} = {}) {
|
|
41
|
+
app.get('/api/validate', async (req, res) => {
|
|
42
|
+
const root = req.workspace?.root;
|
|
43
|
+
if (!root) {
|
|
44
|
+
// No workspace to validate — a guarded failure, not a 500.
|
|
45
|
+
return res.json({ scope: null, findings: [], bySeverity: summarizeFindings([]), unavailable: true });
|
|
46
|
+
}
|
|
47
|
+
const scope = req.query.scope === 'feature' ? 'feature' : 'project';
|
|
48
|
+
const featureCode = typeof req.query.featureCode === 'string' ? req.query.featureCode : null;
|
|
49
|
+
|
|
50
|
+
if (scope === 'feature' && !featureCode) {
|
|
51
|
+
return res.status(400).json({ error: 'scope=feature requires featureCode' });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const result = scope === 'feature'
|
|
56
|
+
? await validateFeature(root, featureCode) // local-only; no `external`
|
|
57
|
+
: await validateProject(root, {}); // local-only; no `external`
|
|
58
|
+
const findings = Array.isArray(result.findings) ? result.findings : [];
|
|
59
|
+
// Pass the validator result through verbatim + add the severity rollup.
|
|
60
|
+
return res.json({ ...result, bySeverity: summarizeFindings(findings) });
|
|
61
|
+
} catch (err) {
|
|
62
|
+
// validateCode throws INVALID_INPUT on a malformed feature code → 400.
|
|
63
|
+
if (err && err.code === 'INVALID_INPUT') {
|
|
64
|
+
return res.status(400).json({ error: err.message });
|
|
65
|
+
}
|
|
66
|
+
// Any other failure degrades to a non-500 unavailable body.
|
|
67
|
+
return res.json({ scope, feature_code: featureCode, findings: [], bySeverity: summarizeFindings([]), unavailable: true, error: err?.message || 'validate failed' });
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
package/server/vision-routes.js
CHANGED
|
@@ -44,6 +44,8 @@ function getSchemaValidator() {
|
|
|
44
44
|
import { randomUUID } from 'node:crypto';
|
|
45
45
|
import { getTargetRoot, resolveProjectPath } from './project-root.js';
|
|
46
46
|
import { resolveFeaturesPathFromConfig } from '../lib/project-paths.js';
|
|
47
|
+
import { getCompletions } from '../lib/completion-writer.js';
|
|
48
|
+
import { isFeatureCode } from '../lib/feature-code.js';
|
|
47
49
|
import { anchorBoundary } from '../lib/checkpoint/checkpoint-writer.js';
|
|
48
50
|
import { appendGateLogEntry, readGateLog, mapResolveOutcomeToSchema } from './gate-log-store.js';
|
|
49
51
|
import { addOpenLoop, resolveOpenLoop, listOpenLoops } from './open-loops-store.js';
|
|
@@ -93,6 +95,33 @@ export function attachVisionRoutes(app, { store, scheduleBroadcast, broadcastMes
|
|
|
93
95
|
const guardAuthEnabled = capabilities?.guardAuth === true;
|
|
94
96
|
const guardAuth = (req, res, next) =>
|
|
95
97
|
guardAuthEnabled ? requireSensitiveToken(req, res, next) : next();
|
|
98
|
+
|
|
99
|
+
// PARITY-5: GET /api/completions — read-only recorded-completion log for a
|
|
100
|
+
// feature. Reads are open (not guardAuth-wrapped); wraps the same
|
|
101
|
+
// getCompletions() the CLI uses so the cockpit and CLI agree byte-for-byte.
|
|
102
|
+
app.get('/api/completions', (req, res) => {
|
|
103
|
+
try {
|
|
104
|
+
const opts = {};
|
|
105
|
+
const fc = req.query.featureCode;
|
|
106
|
+
if (typeof fc === 'string' && fc) {
|
|
107
|
+
// This route is open (no auth) and feature_code is join()'d into a
|
|
108
|
+
// filesystem path downstream (feature-json.js#readFeature). Reject
|
|
109
|
+
// anything that isn't a canonical feature code so `../`-style traversal
|
|
110
|
+
// can't read feature.json outside the features dir.
|
|
111
|
+
if (!isFeatureCode(fc)) {
|
|
112
|
+
return res.status(400).json({ error: 'invalid featureCode' });
|
|
113
|
+
}
|
|
114
|
+
opts.feature_code = fc;
|
|
115
|
+
}
|
|
116
|
+
const rawLimit = parseInt(req.query.limit, 10);
|
|
117
|
+
if (Number.isFinite(rawLimit)) opts.limit = rawLimit;
|
|
118
|
+
const result = getCompletions(getTargetRoot(), opts);
|
|
119
|
+
res.json(result);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
res.status(400).json({ error: err.message || String(err) });
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
96
125
|
// GET /api/vision/items — full state (optional ?group= filter)
|
|
97
126
|
app.get('/api/vision/items', (req, res) => {
|
|
98
127
|
let state = store.getState();
|
package/server/vision-server.js
CHANGED
|
@@ -27,11 +27,15 @@ import { attachSessionRoutes } from './session-routes.js';
|
|
|
27
27
|
import { attachActivityRoutes } from './activity-routes.js';
|
|
28
28
|
import { SettingsStore } from './settings-store.js';
|
|
29
29
|
import { attachSettingsRoutes } from './settings-routes.js';
|
|
30
|
+
import { attachHealthRoutes } from './health-routes.js';
|
|
31
|
+
import { attachValidateRoutes } from './validate-routes.js';
|
|
32
|
+
import { attachQaScopeRoutes } from './qa-scope-routes.js';
|
|
30
33
|
import { attachDesignRoutes } from './design-routes.js';
|
|
31
34
|
import { DesignSessionManager } from './design-session.js';
|
|
32
35
|
import { attachPipelineRoutes } from './pipeline-routes.js';
|
|
33
36
|
import { attachIdeaboxRoutes } from './ideabox-routes.js';
|
|
34
37
|
import { attachBuildRoutes } from './build-routes.js';
|
|
38
|
+
import { attachFeatureScaffoldRoutes } from './feature-scaffold-routes.js';
|
|
35
39
|
import { attachJournalRoutes } from './journal-routes.js';
|
|
36
40
|
import { CoalescingBuffer } from './coalescing-buffer.js';
|
|
37
41
|
/** Settings defaults (previously derived from contracts/lifecycle.json). */
|
|
@@ -85,6 +89,19 @@ export class VisionServer {
|
|
|
85
89
|
broadcastMessage: (msg) => this.broadcastMessage(msg),
|
|
86
90
|
});
|
|
87
91
|
|
|
92
|
+
// ── Environment-health route (COMP-PARITY-3) ──────────────────────────
|
|
93
|
+
// Read-only GET /api/environment-health; resolves its own compose package
|
|
94
|
+
// root + composeBin/Node defaults, reads hooks off req.workspace.
|
|
95
|
+
attachHealthRoutes(app);
|
|
96
|
+
|
|
97
|
+
// ── Cross-artifact validation findings (COMP-PARITY-6) ─────────────────
|
|
98
|
+
// Read-only GET /api/validate; reads workspace off req.workspace.
|
|
99
|
+
attachValidateRoutes(app);
|
|
100
|
+
|
|
101
|
+
// ── QA-scope affected-routes panel (COMP-PARITY-10) ────────────────────
|
|
102
|
+
// Read-only GET /api/qa-scope?featureCode=…; reads off req.workspace.
|
|
103
|
+
attachQaScopeRoutes(app);
|
|
104
|
+
|
|
88
105
|
// ── Vision CRUD + lifecycle routes ─────────────────────────────────────
|
|
89
106
|
attachVisionRoutes(app, {
|
|
90
107
|
store: this.store,
|
|
@@ -152,6 +169,10 @@ export class VisionServer {
|
|
|
152
169
|
// ── Build start/abort routes (sensitive) ───────────────────────────────
|
|
153
170
|
attachBuildRoutes(app);
|
|
154
171
|
|
|
172
|
+
// ── Feature scaffolding (COMP-PARITY-9, sensitive) ─────────────────────
|
|
173
|
+
// POST /api/features/scaffold — writes feature.json + a ROADMAP row.
|
|
174
|
+
attachFeatureScaffoldRoutes(app, { getProjectRoot: () => getTargetRoot() });
|
|
175
|
+
|
|
155
176
|
// ── Build state hydration ─────────────────────────────────────────────
|
|
156
177
|
app.get('/api/build/state', (_req, res) => {
|
|
157
178
|
const buildPath = path.join(getDataDir(), 'active-build.json');
|