From cc770e988c891788dfcec476e7066c13c9db9ea7 Mon Sep 17 00:00:00 2001 From: Dean Zaka Hidayat Date: Thu, 16 Apr 2026 15:39:22 +0700 Subject: [PATCH] fix: update CI scripts to handle apps as subdirectories Apps changed from flat JSON files (apps/default.json) to full directories (apps/default/package.json + src/). Update validate, summary, and assemble scripts to scan for subdirectories instead of top-level JSON files. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/assemble.mjs | 17 ++++++++++++++++- scripts/summary.mjs | 24 ++++++++++++++++++++++-- scripts/validate.mjs | 43 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 72 insertions(+), 12 deletions(-) diff --git a/scripts/assemble.mjs b/scripts/assemble.mjs index 267dcce..638ce65 100644 --- a/scripts/assemble.mjs +++ b/scripts/assemble.mjs @@ -37,6 +37,21 @@ function loadArtifacts(dirName) { })); } +function loadAppArtifacts(dirName) { + const dirPath = path.join(ROOT, dirName); + if (!fs.existsSync(dirPath)) { + return []; + } + + return fs + .readdirSync(dirPath, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => ({ + id: entry.name, + data: readJson(path.join(dirPath, entry.name, "package.json")), + })); +} + // Read manifest const manifest = readJson(path.join(ROOT, "manifest.json")); @@ -46,7 +61,7 @@ const bundle = { agents: loadArtifacts("agents"), projects: loadArtifacts("projects"), automations: loadArtifacts("automations"), - apps: loadArtifacts("apps"), + apps: loadAppArtifacts("apps"), assembledAt: new Date().toISOString(), }; diff --git a/scripts/summary.mjs b/scripts/summary.mjs index 70c7514..5e7dfdc 100644 --- a/scripts/summary.mjs +++ b/scripts/summary.mjs @@ -3,7 +3,8 @@ import path from "node:path"; const ROOT = process.cwd(); -const BUNDLE_DIRS = ["agents", "apps", "automations", "projects"]; +const JSON_DIRS = ["agents", "automations", "projects"]; +const APP_DIR = "apps"; function listJsonFiles(dirName) { const dirPath = path.join(ROOT, dirName); @@ -18,6 +19,19 @@ function listJsonFiles(dirName) { .sort(); } +function listAppDirs(dirName) { + const dirPath = path.join(ROOT, dirName); + if (!fs.existsSync(dirPath)) { + return []; + } + + return fs + .readdirSync(dirPath, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .sort(); +} + function readJson(filePath) { const raw = fs.readFileSync(filePath, "utf8"); return JSON.parse(raw); @@ -41,7 +55,7 @@ console.log(`Name: ${manifest.name ?? "Unknown"}`); console.log(`Space ID: ${manifest.spaceId ?? "Unknown"}`); console.log(`Version: ${manifest.version ?? "Unknown"}`); -for (const dirName of BUNDLE_DIRS) { +for (const dirName of JSON_DIRS) { const files = listJsonFiles(dirName); printHeader(`${dirName} (${files.length})`); @@ -51,4 +65,10 @@ for (const dirName of BUNDLE_DIRS) { } } +const appDirs = listAppDirs(APP_DIR); +printHeader(`${APP_DIR} (${appDirs.length})`); +for (const name of appDirs) { + console.log(`- ${name}`); +} + console.log("\nSummary completed."); diff --git a/scripts/validate.mjs b/scripts/validate.mjs index 3e4b49d..aa1e2d8 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -3,7 +3,8 @@ import path from "node:path"; const ROOT = process.cwd(); -const REQUIRED_DIRS = ["agents", "apps", "automations", "projects"]; +const JSON_DIRS = ["agents", "automations", "projects"]; +const APP_DIR = "apps"; const errors = []; @@ -46,6 +47,25 @@ function listJsonFiles(dirName) { return files; } +function listAppDirs(dirName) { + const dirPath = path.join(ROOT, dirName); + if (!fs.existsSync(dirPath)) { + fail(`Missing directory: ${dirName}`); + return []; + } + + const dirs = fs + .readdirSync(dirPath, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => path.join(dirPath, entry.name)); + + if (dirs.length === 0) { + fail(`Directory has no app subdirectories: ${dirName}`); + } + + return dirs; +} + function validateManifest() { const filePath = path.join(ROOT, "manifest.json"); if (!fs.existsSync(filePath)) { @@ -87,17 +107,21 @@ function validateAgents() { } function validateApps() { - for (const filePath of listJsonFiles("apps")) { - const data = readJson(filePath); + for (const appDir of listAppDirs(APP_DIR)) { + const pkgPath = path.join(appDir, "package.json"); + const rel = path.relative(ROOT, appDir); + + if (!fs.existsSync(pkgPath)) { + fail(`${rel}: missing package.json`); + continue; + } + + const data = readJson(pkgPath); if (data == null) { continue; } - const rel = path.relative(ROOT, filePath); - assert( - typeof data.src === "object" && data.src != null, - `${rel}: src object is required`, - ); + assert(typeof data.name === "string", `${rel}/package.json: name must be a string`); } } @@ -138,9 +162,10 @@ function validateProjects() { validateManifest(); -for (const dirName of REQUIRED_DIRS) { +for (const dirName of JSON_DIRS) { listJsonFiles(dirName); } +listAppDirs(APP_DIR); validateAgents(); validateApps();