@codeyam/codeyam-cli 0.1.22 → 0.1.24
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/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +135 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/nodeToSource.ts +19 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +11 -4
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +5 -1
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1632 -1554
- package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +7 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +7 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
- package/analyzer-template/project/runMultiScenarioServer.ts +26 -3
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js +23 -3
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js +47 -0
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +17 -9
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -1
- package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js +30 -0
- package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js.map +1 -0
- package/codeyam-cli/src/commands/editor.js +207 -41
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js +23 -0
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js.map +1 -0
- package/codeyam-cli/src/data/designSystems.js +27 -0
- package/codeyam-cli/src/data/designSystems.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js +44 -0
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +103 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +140 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +50 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
- package/codeyam-cli/src/utils/editorApi.js +16 -0
- package/codeyam-cli/src/utils/editorApi.js.map +1 -1
- package/codeyam-cli/src/utils/editorAudit.js +38 -2
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarios.js +60 -0
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/utils/editorSeedAdapter.js +42 -2
- package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
- package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js +159 -0
- package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js.map +1 -0
- package/codeyam-cli/src/utils/queue/job.js +9 -1
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js +98 -0
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +30 -11
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
- package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js +34 -0
- package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js.map +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CKeQT5Ty.js → InteractivePreview-DtYTSPL2.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DUMfcNVK.js → ScenarioViewer-CefgqbCr.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/Spinner-Bc8BG-Lw.js +34 -0
- package/codeyam-cli/src/webserver/build/client/assets/{_index-BAWd-Xjf.js → _index-C1YkzTAV.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BOARiB-g.js → activity.(_tab)-yH46LLUz.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-verify-routes-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.interactive-switch-scenario-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-C8y4mmyv.js → dev.empty-CRepiabR.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{editor.entity.(_sha)-aIHKLB-m.js → editor.entity.(_sha)-oBrbke_R.js} +19 -19
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-ByHz6rAQ.js → entity._sha._-DYJRGiDI.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-CmLO432x.js → entity._sha.scenarios._scenarioId.dev-wdiwx5-Z.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-Bz9sCUF_.js → entity._sha.scenarios._scenarioId.fullscreen-BrkN-40Y.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DQM8E7L4.js → entity._sha_.create-scenario-DxfhekTZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-CAoXLsQr.js → entity._sha_.edit._scenarioId-CRXJWmpB.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-694b698a.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{root-D2_tktnk.js → root-DXjFYOxD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-D9QZKaLJ.js +2 -0
- package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-DjF-soOH.js → analysisRunner-zEYtiv0T.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-nAvHGWbz.js → index-CcHPEbhi.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-XhpIt-OT.js → init-D68IyWbU.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{server-build-DVwiibFu.js → server-build-Cxzo0Zp2.js} +192 -148
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/editorProxy.js +55 -3
- package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +1 -2
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/codeyam-editor-reference.md +8 -6
- package/codeyam-cli/templates/design-systems/clean-dashboard-design-system.md +255 -0
- package/codeyam-cli/templates/design-systems/editorial-design-system.md +267 -0
- package/codeyam-cli/templates/design-systems/mono-brutalist-design-system.md +256 -0
- package/codeyam-cli/templates/design-systems/neo-brutalist-design-system.md +294 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +47 -34
- package/codeyam-cli/templates/seed-adapters/supabase.ts +14 -5
- package/package.json +1 -1
- package/packages/ai/src/lib/astScopes/methodSemantics.js +99 -0
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/nodeToSource.js +16 -0
- package/packages/ai/src/lib/astScopes/nodeToSource.js.map +1 -1
- package/packages/ai/src/lib/astScopes/paths.js +12 -3
- package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +5 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +1330 -1270
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/database/src/lib/loadAnalysis.js +7 -1
- package/packages/database/src/lib/loadAnalysis.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/Spinner-D0LgAaSa.js +0 -34
- package/codeyam-cli/src/webserver/build/client/assets/manifest-bcbb3d49.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-BNd5hYuW.js +0 -2
|
@@ -13,6 +13,7 @@ import { installClaudeCodeSkills } from "../utils/install-skills.js";
|
|
|
13
13
|
import { setupClaudeCodeSettings } from "../utils/setupClaudeCodeSettings.js";
|
|
14
14
|
import { ensureAnalyzerFinalized, } from "../utils/analyzerFinalization.js";
|
|
15
15
|
import { APP_FORMATS, TECH_STACKS } from "../data/techStacks.js";
|
|
16
|
+
import { DESIGN_SYSTEMS } from "../data/designSystems.js";
|
|
16
17
|
import { getProjectRoot as getStateProjectRoot } from "../state.js";
|
|
17
18
|
import initCommand from "./init.js";
|
|
18
19
|
import { scanScenarioFiles, syncScenarioFilesToDatabase, backfillScenarioMetadata, migrateScenarioFormats, } from "../utils/scenariosManifest.js";
|
|
@@ -714,11 +715,17 @@ function printSetup(root) {
|
|
|
714
715
|
console.log();
|
|
715
716
|
// ── Design System ────────────────────────────────────────────────
|
|
716
717
|
console.log(chalk.bold('Design System (ask FIRST):'));
|
|
717
|
-
console.log(chalk.dim(' Ask: "
|
|
718
|
+
console.log(chalk.dim(' Ask: "What visual style do you want? Pick a built-in design system or bring your own."'));
|
|
718
719
|
console.log(chalk.dim(' Use AskUserQuestion with these EXACT option labels:'));
|
|
719
|
-
console.log(
|
|
720
|
+
console.log();
|
|
721
|
+
for (const ds of DESIGN_SYSTEMS) {
|
|
722
|
+
console.log(chalk.yellow(` Option label: "${ds.name}"`) +
|
|
723
|
+
chalk.dim(` — ${ds.description}`));
|
|
724
|
+
console.log(chalk.dim(` → Run: codeyam editor design-system ${ds.id}`));
|
|
725
|
+
}
|
|
726
|
+
console.log(chalk.yellow(' Option label: "I\'ll paste my own design system"'));
|
|
720
727
|
console.log(chalk.dim(' → Wait for paste, save to .codeyam/design-system.md, confirm with brief summary'));
|
|
721
|
-
console.log(chalk.yellow(' Option
|
|
728
|
+
console.log(chalk.yellow(' Option label: "Skip — use sensible defaults"'));
|
|
722
729
|
console.log(chalk.dim(' → Skip'));
|
|
723
730
|
console.log();
|
|
724
731
|
console.log(chalk.bold('Checklist:'));
|
|
@@ -1132,14 +1139,13 @@ function printStep4(root, feature) {
|
|
|
1132
1139
|
console.log('Verify everything works before presenting the prototype.');
|
|
1133
1140
|
console.log();
|
|
1134
1141
|
console.log(chalk.bold('Verify the dev server:'));
|
|
1135
|
-
console.log(chalk.dim(
|
|
1136
|
-
console.log(chalk.dim(
|
|
1137
|
-
console.log(chalk.dim(' # Check API routes: curl -s http://localhost:<dev-port>/api/your-route'));
|
|
1142
|
+
console.log(chalk.dim(' # Verify pages and API routes load:'));
|
|
1143
|
+
console.log(chalk.dim(` codeyam editor verify-routes '{"paths":["/your-page"],"apiRoutes":["/api/your-route"]}'`));
|
|
1138
1144
|
console.log();
|
|
1139
1145
|
console.log(chalk.bold('Verify before proceeding:'));
|
|
1140
1146
|
console.log(chalk.yellow(' Verify everything works before presenting the prototype to the user.'));
|
|
1141
|
-
checkbox('Verify
|
|
1142
|
-
|
|
1147
|
+
checkbox('Verify page and API routes: `codeyam editor verify-routes \'{"paths":["/"],"apiRoutes":["/api/your-route"]}\'`');
|
|
1148
|
+
console.log(chalk.dim(' Include ALL page paths you built and ALL API routes they depend on.'));
|
|
1143
1149
|
checkbox('Check for broken images: `codeyam editor verify-images \'{"paths":["/"], "imageUrls":["url1","url2"]}\'`');
|
|
1144
1150
|
console.log(chalk.dim(' Pass ALL page paths and ALL image URLs you used in seed data / API responses.'));
|
|
1145
1151
|
console.log(chalk.dim(' Client-rendered pages need imageUrls — the HTML shell has no images to scan.'));
|
|
@@ -1182,7 +1188,7 @@ function printStep5(root, feature) {
|
|
|
1182
1188
|
console.log();
|
|
1183
1189
|
console.log(chalk.bold('Before presenting — verify everything works:'));
|
|
1184
1190
|
checkbox(`Refresh the preview: \`codeyam editor preview '{"dimension":"${dim}"}'\` — check the \`preview\` field for \`healthy: false\``);
|
|
1185
|
-
checkbox('Verify
|
|
1191
|
+
checkbox('Verify routes: `codeyam editor verify-routes \'{"paths":["/"],"apiRoutes":["/api/your-route"]}\'`');
|
|
1186
1192
|
console.log();
|
|
1187
1193
|
console.log(chalk.bold.red(' Verify EVERY image loads (this is the #1 source of broken prototypes):'));
|
|
1188
1194
|
checkbox('Run `codeyam editor verify-images \'{"paths":["/"], "imageUrls":["url1","url2"]}\'`');
|
|
@@ -1978,7 +1984,7 @@ function printMigrateStep8(root) {
|
|
|
1978
1984
|
printComponentCaptureInstructions();
|
|
1979
1985
|
console.log();
|
|
1980
1986
|
console.log(chalk.bold('Verify:'));
|
|
1981
|
-
checkbox('Run `codeyam editor analyze-imports` to populate import graph');
|
|
1987
|
+
checkbox('Run `codeyam editor analyze-imports` to populate import graph (or `codeyam editor analyze-imports path/to/file.tsx ...` for specific files)');
|
|
1982
1988
|
checkbox('Run library function tests: `npx jest --testPathPattern="<relevant>" --maxWorkers=2`');
|
|
1983
1989
|
checkbox('Run `codeyam editor audit` to check completeness');
|
|
1984
1990
|
checkbox('Check for client errors: `codeyam editor client-errors`');
|
|
@@ -2356,10 +2362,14 @@ async function handleAnalyzeImports(options = {}) {
|
|
|
2356
2362
|
glossaryEntries = sanitizeGlossaryEntries(parsed);
|
|
2357
2363
|
}
|
|
2358
2364
|
catch {
|
|
2365
|
+
if (options.silent)
|
|
2366
|
+
return;
|
|
2359
2367
|
console.error(chalk.red('Error: Could not parse .codeyam/glossary.json.'));
|
|
2360
2368
|
process.exit(1);
|
|
2361
2369
|
}
|
|
2362
2370
|
if (glossaryEntries.length === 0) {
|
|
2371
|
+
if (options.silent)
|
|
2372
|
+
return;
|
|
2363
2373
|
console.error(chalk.red('Error: glossary.json is empty.'));
|
|
2364
2374
|
process.exit(1);
|
|
2365
2375
|
}
|
|
@@ -2428,6 +2438,15 @@ async function handleAnalyzeImports(options = {}) {
|
|
|
2428
2438
|
catch {
|
|
2429
2439
|
// Non-fatal — fall back to analyzing all files
|
|
2430
2440
|
}
|
|
2441
|
+
// If specific file paths were requested, scope analysis to only those files.
|
|
2442
|
+
// The full filePaths set is still used for the import graph below.
|
|
2443
|
+
if (options.filePaths && options.filePaths.length > 0) {
|
|
2444
|
+
const requested = new Set(options.filePaths);
|
|
2445
|
+
targetFilePaths = targetFilePaths.filter((fp) => requested.has(fp));
|
|
2446
|
+
if (targetFilePaths.length === 0 && !options.silent) {
|
|
2447
|
+
console.log(chalk.dim('Requested file(s) already analyzed or not in glossary — skipping analysis.'));
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2431
2450
|
// Run data-structure-only analysis for entities that need it.
|
|
2432
2451
|
// Don't pass entityNames — entities may not exist yet (fresh clone).
|
|
2433
2452
|
// The analyzer will discover and create them from file paths.
|
|
@@ -2444,6 +2463,10 @@ async function handleAnalyzeImports(options = {}) {
|
|
|
2444
2463
|
catch (err) {
|
|
2445
2464
|
progress.fail('Analysis failed');
|
|
2446
2465
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2466
|
+
if (options.silent) {
|
|
2467
|
+
// Internal caller — don't kill the process, let the caller handle it
|
|
2468
|
+
return;
|
|
2469
|
+
}
|
|
2447
2470
|
console.error(chalk.red(`Error: ${msg}`));
|
|
2448
2471
|
process.exit(1);
|
|
2449
2472
|
}
|
|
@@ -2499,18 +2522,10 @@ async function handleAnalyzeImports(options = {}) {
|
|
|
2499
2522
|
}
|
|
2500
2523
|
}
|
|
2501
2524
|
}
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
const entry = glossary.find((e) => e.filePath === fp);
|
|
2507
|
-
updatedFailures[fp] = {
|
|
2508
|
-
entityName: entry?.name || path.basename(fp, path.extname(fp)),
|
|
2509
|
-
error: `Automated analysis failed — see .codeyam/analysis-errors.txt`,
|
|
2510
|
-
failedAt: now,
|
|
2511
|
-
};
|
|
2512
|
-
}
|
|
2513
|
-
}
|
|
2525
|
+
// When we can't parse specific entity names from the error, DON'T mark
|
|
2526
|
+
// all target files as failed. The error may be non-fatal (e.g., a cache
|
|
2527
|
+
// miss logged as "CodeYam Error") and blanket-marking every file as
|
|
2528
|
+
// permanently failed blocks future audits from resolving them.
|
|
2514
2529
|
writeAnalysisFailures(root, updatedFailures);
|
|
2515
2530
|
}
|
|
2516
2531
|
catch {
|
|
@@ -2709,6 +2724,24 @@ async function handleDelete(scenarioId) {
|
|
|
2709
2724
|
* Creates isolation route directories and the layout guard file.
|
|
2710
2725
|
* This avoids brace-expansion permission prompts in the embedded terminal.
|
|
2711
2726
|
*/
|
|
2727
|
+
function handleDesignSystem(designSystemId) {
|
|
2728
|
+
const root = process.cwd();
|
|
2729
|
+
const ds = DESIGN_SYSTEMS.find((d) => d.id === designSystemId);
|
|
2730
|
+
if (!ds) {
|
|
2731
|
+
console.error(chalk.red(`Error: Unknown design system "${designSystemId}". Valid options: ${DESIGN_SYSTEMS.map((d) => d.id).join(', ')}`));
|
|
2732
|
+
process.exit(1);
|
|
2733
|
+
}
|
|
2734
|
+
const srcPath = path.join(__dirname, '..', '..', 'templates', 'design-systems', ds.fileName);
|
|
2735
|
+
if (!fs.existsSync(srcPath)) {
|
|
2736
|
+
console.error(chalk.red(`Error: Design system file not found: ${srcPath}`));
|
|
2737
|
+
process.exit(1);
|
|
2738
|
+
}
|
|
2739
|
+
const destDir = path.join(root, '.codeyam');
|
|
2740
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
2741
|
+
const destPath = path.join(destDir, 'design-system.md');
|
|
2742
|
+
fs.copyFileSync(srcPath, destPath);
|
|
2743
|
+
console.log(chalk.green(`Installed "${ds.name}" design system → .codeyam/design-system.md`));
|
|
2744
|
+
}
|
|
2712
2745
|
function handleIsolate(componentNames) {
|
|
2713
2746
|
const root = process.cwd();
|
|
2714
2747
|
if (componentNames.length === 0) {
|
|
@@ -2848,6 +2881,34 @@ function formatApiSubcommandResult(subcommand, data) {
|
|
|
2848
2881
|
}
|
|
2849
2882
|
return parts.join(' ');
|
|
2850
2883
|
}
|
|
2884
|
+
case 'verify-routes': {
|
|
2885
|
+
const lines = [];
|
|
2886
|
+
lines.push(chalk.bold.yellow('━━━ Route Verification ━━━'));
|
|
2887
|
+
for (const [route, info] of Object.entries(data.routes || {})) {
|
|
2888
|
+
const r = info;
|
|
2889
|
+
if (r.ok) {
|
|
2890
|
+
lines.push(chalk.green(` ✓ ${route} — HTTP ${r.status}`));
|
|
2891
|
+
}
|
|
2892
|
+
else {
|
|
2893
|
+
lines.push(chalk.red(` ✗ ${route} — ${r.error || `HTTP ${r.status}`}`));
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
for (const [route, info] of Object.entries(data.apiRoutes || {})) {
|
|
2897
|
+
const r = info;
|
|
2898
|
+
if (r.ok && r.isJSON) {
|
|
2899
|
+
lines.push(chalk.green(` ✓ ${route} — HTTP ${r.status}, valid JSON`));
|
|
2900
|
+
}
|
|
2901
|
+
else if (r.ok) {
|
|
2902
|
+
lines.push(chalk.yellow(` ⚠ ${route} — HTTP ${r.status}, not valid JSON`));
|
|
2903
|
+
}
|
|
2904
|
+
else {
|
|
2905
|
+
lines.push(chalk.red(` ✗ ${route} — ${r.error || `HTTP ${r.status}`}`));
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
lines.push('');
|
|
2909
|
+
lines.push(data.ok ? chalk.green(data.summary) : chalk.red(data.summary));
|
|
2910
|
+
return lines.join('\n');
|
|
2911
|
+
}
|
|
2851
2912
|
default:
|
|
2852
2913
|
return null; // journal-list, show/hide-results: keep full JSON
|
|
2853
2914
|
}
|
|
@@ -3454,7 +3515,15 @@ function printAuditGateFailures(data) {
|
|
|
3454
3515
|
for (const m of missingGlossary) {
|
|
3455
3516
|
issues.push(` → ${m.name} (${m.filePath})`);
|
|
3456
3517
|
}
|
|
3457
|
-
|
|
3518
|
+
const missingPaths = missingGlossary
|
|
3519
|
+
.map((m) => m.filePath)
|
|
3520
|
+
.filter(Boolean);
|
|
3521
|
+
if (missingPaths.length > 0) {
|
|
3522
|
+
issues.push(` Fix: Run \`codeyam editor analyze-imports ${missingPaths.join(' ')}\``);
|
|
3523
|
+
}
|
|
3524
|
+
else {
|
|
3525
|
+
issues.push(` Fix: Run \`codeyam editor analyze-imports\` to add these files to the glossary`);
|
|
3526
|
+
}
|
|
3458
3527
|
}
|
|
3459
3528
|
if (s.incompleteEntities > 0) {
|
|
3460
3529
|
// Check for persistent analysis failures
|
|
@@ -3498,8 +3567,16 @@ function printAuditGateFailures(data) {
|
|
|
3498
3567
|
}
|
|
3499
3568
|
}
|
|
3500
3569
|
if (s.unassociatedScenarios > 0) {
|
|
3501
|
-
issues.push(`${s.unassociatedScenarios} component(s) have scenarios with no entity link — run \`codeyam editor analyze-imports\` then re-run audit`);
|
|
3502
3570
|
const unassociated = data.unassociatedScenarios || [];
|
|
3571
|
+
const unassocPaths = unassociated
|
|
3572
|
+
.map((u) => u.filePath)
|
|
3573
|
+
.filter(Boolean);
|
|
3574
|
+
if (unassocPaths.length > 0) {
|
|
3575
|
+
issues.push(`${s.unassociatedScenarios} component(s) have scenarios with no entity link — run \`codeyam editor analyze-imports ${unassocPaths.join(' ')}\` then re-run audit`);
|
|
3576
|
+
}
|
|
3577
|
+
else {
|
|
3578
|
+
issues.push(`${s.unassociatedScenarios} component(s) have scenarios with no entity link — run \`codeyam editor analyze-imports\` then re-run audit`);
|
|
3579
|
+
}
|
|
3503
3580
|
for (const u of unassociated) {
|
|
3504
3581
|
issues.push(` → ${u.name} (${u.filePath}) — ${u.scenarioCount} scenario${u.scenarioCount !== 1 ? 's' : ''}`);
|
|
3505
3582
|
}
|
|
@@ -3554,16 +3631,16 @@ function printAuditGateFailures(data) {
|
|
|
3554
3631
|
* which glossary components have registered scenarios and which functions
|
|
3555
3632
|
* have test files. Exits with code 1 if anything is missing.
|
|
3556
3633
|
*/
|
|
3557
|
-
async function handleAudit() {
|
|
3634
|
+
async function handleAudit(options) {
|
|
3558
3635
|
let data = await fetchAuditResult();
|
|
3559
3636
|
if (!data) {
|
|
3560
3637
|
console.error(chalk.red('Error: Could not reach the CodeYam server. Is it running?'));
|
|
3561
3638
|
process.exit(1);
|
|
3562
3639
|
}
|
|
3563
|
-
//
|
|
3564
|
-
//
|
|
3565
|
-
//
|
|
3566
|
-
//
|
|
3640
|
+
// Two-phase auto-fix for entity associations:
|
|
3641
|
+
// Phase 1: DB-only backfill — fast, matches existing entities to scenarios.
|
|
3642
|
+
// Phase 2: If backfill fails, targeted analyze-imports for only the
|
|
3643
|
+
// specific unresolved files (1-3 files, not the full glossary scan).
|
|
3567
3644
|
const incompleteBeforeFix = data.incompleteEntities || [];
|
|
3568
3645
|
const unassociatedBeforeFix = data.unassociatedScenarios || [];
|
|
3569
3646
|
let autoRemediationFailed = false;
|
|
@@ -3595,14 +3672,58 @@ async function handleAudit() {
|
|
|
3595
3672
|
console.error(chalk.red('Error: Could not reach the CodeYam server after backfill.'));
|
|
3596
3673
|
process.exit(1);
|
|
3597
3674
|
}
|
|
3598
|
-
// If issues persist after backfill,
|
|
3675
|
+
// If issues persist after DB-only backfill, run targeted analyze-imports
|
|
3676
|
+
// for ONLY the specific files that need entities. This is fast (1-3 files)
|
|
3677
|
+
// unlike full analyze-imports which scans all glossary entries.
|
|
3678
|
+
const incompleteAfterBackfill = data.incompleteEntities || [];
|
|
3679
|
+
const unassociatedAfterBackfill = data.unassociatedScenarios || [];
|
|
3680
|
+
if (incompleteAfterBackfill.length > 0 ||
|
|
3681
|
+
unassociatedAfterBackfill.length > 0) {
|
|
3682
|
+
const { determineTargetedAnalysisPaths } = await import('../utils/editorAudit.js');
|
|
3683
|
+
const targetPaths = determineTargetedAnalysisPaths({
|
|
3684
|
+
unassociatedScenarios: unassociatedAfterBackfill,
|
|
3685
|
+
incompleteEntities: incompleteAfterBackfill,
|
|
3686
|
+
});
|
|
3687
|
+
if (targetPaths.length > 0) {
|
|
3688
|
+
console.log(chalk.dim(`Running targeted analysis for ${targetPaths.length} file${targetPaths.length !== 1 ? 's' : ''}...`));
|
|
3689
|
+
try {
|
|
3690
|
+
await handleAnalyzeImports({
|
|
3691
|
+
silent: true,
|
|
3692
|
+
filePaths: targetPaths,
|
|
3693
|
+
});
|
|
3694
|
+
// Retry backfill after analysis created entities
|
|
3695
|
+
const entities = await loadEntities({});
|
|
3696
|
+
if (entities && entities.length > 0) {
|
|
3697
|
+
const { getDatabase: getDb } = await import('../../../packages/database/index.js');
|
|
3698
|
+
const freshDb = getDb();
|
|
3699
|
+
await backfillEntityShaOnScenarios(freshDb, entities.map((e) => ({
|
|
3700
|
+
sha: e.sha,
|
|
3701
|
+
name: e.name,
|
|
3702
|
+
filePath: e.filePath || '',
|
|
3703
|
+
isDefaultExport: e.metadata?.notExported === false &&
|
|
3704
|
+
e.metadata?.namedExport === false,
|
|
3705
|
+
})));
|
|
3706
|
+
}
|
|
3707
|
+
// Re-fetch audit results after targeted analysis
|
|
3708
|
+
data = await fetchAuditResult({ skipTests: true });
|
|
3709
|
+
if (!data) {
|
|
3710
|
+
console.error(chalk.red('Error: Could not reach the CodeYam server after analysis.'));
|
|
3711
|
+
process.exit(1);
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
catch {
|
|
3715
|
+
// Targeted analysis failed — fall through to show remaining issues
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
// Check if issues persist after all remediation attempts
|
|
3599
3720
|
const incompleteAfterFix = data.incompleteEntities || [];
|
|
3600
3721
|
const unassociatedAfterFix = data.unassociatedScenarios || [];
|
|
3601
3722
|
if (incompleteAfterFix.length > 0 || unassociatedAfterFix.length > 0) {
|
|
3602
3723
|
autoRemediationFailed = true;
|
|
3603
3724
|
}
|
|
3604
3725
|
}
|
|
3605
|
-
|
|
3726
|
+
let { components, functions, summary } = data;
|
|
3606
3727
|
console.log();
|
|
3607
3728
|
console.log(chalk.bold.cyan('━━━ Editor Audit ━━━'));
|
|
3608
3729
|
console.log();
|
|
@@ -3701,7 +3822,15 @@ async function handleAudit() {
|
|
|
3701
3822
|
for (const m of missingFromGlossary) {
|
|
3702
3823
|
console.log(` ${chalk.red('✗')} ${m.name} ${chalk.dim(`(${m.filePath})`)} — ${m.scenarioCount} scenario${m.scenarioCount !== 1 ? 's' : ''} but not in glossary`);
|
|
3703
3824
|
}
|
|
3704
|
-
|
|
3825
|
+
const mgPaths = missingFromGlossary
|
|
3826
|
+
.map((m) => m.filePath)
|
|
3827
|
+
.filter(Boolean);
|
|
3828
|
+
if (mgPaths.length > 0) {
|
|
3829
|
+
console.log(chalk.yellow(` Add these to .codeyam/glossary.json and run \`codeyam editor analyze-imports ${mgPaths.join(' ')}\``));
|
|
3830
|
+
}
|
|
3831
|
+
else {
|
|
3832
|
+
console.log(chalk.yellow(' Add these to .codeyam/glossary.json and run `codeyam editor analyze-imports`'));
|
|
3833
|
+
}
|
|
3705
3834
|
console.log();
|
|
3706
3835
|
}
|
|
3707
3836
|
// Incomplete entities (scenarios without analyses) — report with guidance.
|
|
@@ -3756,12 +3885,18 @@ async function handleAudit() {
|
|
|
3756
3885
|
console.log(chalk.dim(` … and ${u.scenarioNames.length - 3} more`));
|
|
3757
3886
|
}
|
|
3758
3887
|
}
|
|
3888
|
+
const uaPaths = unassociatedScenarios
|
|
3889
|
+
.map((u) => u.filePath)
|
|
3890
|
+
.filter(Boolean);
|
|
3891
|
+
const uaCmd = uaPaths.length > 0
|
|
3892
|
+
? `codeyam editor analyze-imports ${uaPaths.join(' ')}`
|
|
3893
|
+
: 'codeyam editor analyze-imports';
|
|
3759
3894
|
if (autoRemediationFailed) {
|
|
3760
3895
|
console.log(chalk.yellow(' analyze-imports ran automatically but could not resolve these.'));
|
|
3761
|
-
console.log(chalk.yellow(
|
|
3896
|
+
console.log(chalk.yellow(` Run \`${uaCmd}\` to see the full error output.`));
|
|
3762
3897
|
}
|
|
3763
3898
|
else {
|
|
3764
|
-
console.log(chalk.yellow(
|
|
3899
|
+
console.log(chalk.yellow(` Run \`${uaCmd}\` to create entity records, then re-run audit to backfill.`));
|
|
3765
3900
|
}
|
|
3766
3901
|
const unassocErrorReportPath = path.join(getProjectRoot(), '.codeyam', 'analysis-errors.txt');
|
|
3767
3902
|
if (fs.existsSync(unassocErrorReportPath)) {
|
|
@@ -3794,7 +3929,26 @@ async function handleAudit() {
|
|
|
3794
3929
|
: `${s.status.status}`;
|
|
3795
3930
|
console.log(` ${chalk.red('✗')} ${s.scenarioName} ${chalk.dim(`(${s.entityName} — ${reason})`)}`);
|
|
3796
3931
|
}
|
|
3797
|
-
|
|
3932
|
+
if (options?.fix) {
|
|
3933
|
+
// --fix: auto-recapture stale scenarios instead of just reporting them
|
|
3934
|
+
const { shouldAutoRecapture } = await import('../utils/editorAudit.js');
|
|
3935
|
+
if (shouldAutoRecapture({ fix: true, scenariosNeedingRecapture })) {
|
|
3936
|
+
console.log(chalk.cyan(' --fix: auto-recapturing stale scenarios...'));
|
|
3937
|
+
console.log();
|
|
3938
|
+
await handleRecaptureStale();
|
|
3939
|
+
// Re-fetch audit results so the summary and exit code reflect
|
|
3940
|
+
// the post-fix state, not the pre-fix state.
|
|
3941
|
+
const refreshed = await fetchAuditResult({ skipTests: true });
|
|
3942
|
+
if (refreshed) {
|
|
3943
|
+
data = refreshed;
|
|
3944
|
+
({ components, functions, summary } = data);
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
else {
|
|
3949
|
+
console.log(chalk.yellow(' Run: codeyam editor recapture-stale'));
|
|
3950
|
+
console.log(chalk.dim(' Or: codeyam editor audit --fix (to auto-recapture)'));
|
|
3951
|
+
}
|
|
3798
3952
|
console.log();
|
|
3799
3953
|
}
|
|
3800
3954
|
// Duplicate glossary names (warning, not a failure)
|
|
@@ -4764,8 +4918,8 @@ const editorCommand = {
|
|
|
4764
4918
|
describe: 'Editor mode guided workflow',
|
|
4765
4919
|
builder: (yargs) => {
|
|
4766
4920
|
const stepDescription = IS_INTERNAL_BUILD
|
|
4767
|
-
? 'Step number (1-18) or subcommand (template, register, isolate, analyze-imports, manual-entity, dependents, audit, scenarios, scenario-coverage, recapture-stale, change, sync, debug, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors, task-ontrack)'
|
|
4768
|
-
: 'Step number (1-18) or subcommand (template, register, isolate, analyze-imports, manual-entity, dependents, audit, scenarios, scenario-coverage, recapture-stale, change, sync, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors, task-ontrack)';
|
|
4921
|
+
? 'Step number (1-18) or subcommand (template, register, isolate, analyze-imports, manual-entity, dependents, audit, scenarios, scenario-coverage, recapture-stale, change, sync, debug, design-system, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors, task-ontrack)'
|
|
4922
|
+
: 'Step number (1-18) or subcommand (template, register, isolate, analyze-imports, manual-entity, dependents, audit, scenarios, scenario-coverage, recapture-stale, change, sync, design-system, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors, task-ontrack)';
|
|
4769
4923
|
let builder = yargs
|
|
4770
4924
|
.positional('step', {
|
|
4771
4925
|
type: 'string',
|
|
@@ -4796,6 +4950,11 @@ const editorCommand = {
|
|
|
4796
4950
|
alias: 'p',
|
|
4797
4951
|
describe: 'Port to run the web server on',
|
|
4798
4952
|
default: 3111,
|
|
4953
|
+
})
|
|
4954
|
+
.option('fix', {
|
|
4955
|
+
type: 'boolean',
|
|
4956
|
+
describe: 'For audit: also recapture stale scenarios after displaying results',
|
|
4957
|
+
default: false,
|
|
4799
4958
|
});
|
|
4800
4959
|
if (IS_INTERNAL_BUILD) {
|
|
4801
4960
|
builder = builder
|
|
@@ -4923,9 +5082,11 @@ const editorCommand = {
|
|
|
4923
5082
|
fs.writeFileSync(trackingPath, JSON.stringify({ step: state.step, taskCreated: true }, null, 2), 'utf8');
|
|
4924
5083
|
return;
|
|
4925
5084
|
}
|
|
4926
|
-
// Subcommand: codeyam editor analyze-imports
|
|
5085
|
+
// Subcommand: codeyam editor analyze-imports [file1.tsx file2.tsx ...]
|
|
4927
5086
|
if (argv.step === 'analyze-imports') {
|
|
4928
|
-
await
|
|
5087
|
+
const { parseAnalyzeImportsArgs } = await import('./editorAnalyzeImportsArgs.js');
|
|
5088
|
+
const requestedPaths = parseAnalyzeImportsArgs(argv.json, argv._);
|
|
5089
|
+
await handleAnalyzeImports(requestedPaths.length > 0 ? { filePaths: requestedPaths } : {});
|
|
4929
5090
|
return;
|
|
4930
5091
|
}
|
|
4931
5092
|
// Subcommand: codeyam editor manual-entity <JSON|@file>
|
|
@@ -4938,9 +5099,9 @@ const editorCommand = {
|
|
|
4938
5099
|
await handleDependents(argv.json || '');
|
|
4939
5100
|
return;
|
|
4940
5101
|
}
|
|
4941
|
-
// Subcommand: codeyam editor audit
|
|
5102
|
+
// Subcommand: codeyam editor audit [--fix]
|
|
4942
5103
|
if (argv.step === 'audit') {
|
|
4943
|
-
await handleAudit();
|
|
5104
|
+
await handleAudit({ fix: argv.fix || false });
|
|
4944
5105
|
return;
|
|
4945
5106
|
}
|
|
4946
5107
|
// Subcommand: codeyam editor scenarios
|
|
@@ -4973,6 +5134,11 @@ const editorCommand = {
|
|
|
4973
5134
|
await handleValidateSeed(argv.json || '');
|
|
4974
5135
|
return;
|
|
4975
5136
|
}
|
|
5137
|
+
// Subcommand: codeyam editor design-system <id>
|
|
5138
|
+
if (argv.step === 'design-system') {
|
|
5139
|
+
handleDesignSystem(argv.json || '');
|
|
5140
|
+
return;
|
|
5141
|
+
}
|
|
4976
5142
|
// Subcommand: codeyam editor delete <scenarioId>
|
|
4977
5143
|
if (argv.step === 'delete') {
|
|
4978
5144
|
await handleDelete(argv.json || '');
|