@codeyam/codeyam-cli 0.1.15 → 0.1.17
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 +6 -6
- package/analyzer-template/log.txt +3 -3
- package/codeyam-cli/src/commands/editor.js +132 -9
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/commands/init.js +1 -0
- package/codeyam-cli/src/commands/init.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +212 -10
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js +137 -0
- package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +70 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +51 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +20 -1
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js +177 -0
- package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +57 -0
- package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +41 -0
- package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -1
- package/codeyam-cli/src/utils/editorAudit.js +51 -11
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarioSwitch.js +24 -2
- package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarios.js +28 -1
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/utils/entityChangeStatus.js +1 -1
- package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -1
- package/codeyam-cli/src/utils/glossaryAdd.js +74 -0
- package/codeyam-cli/src/utils/glossaryAdd.js.map +1 -0
- package/codeyam-cli/src/utils/install-skills.js +5 -0
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/scenarioCoverage.js +4 -1
- package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -1
- package/codeyam-cli/src/utils/scenariosManifest.js +6 -0
- package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +40 -0
- package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +92 -21
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js +7 -1
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{editor.entity.(_sha)-B7xQ9Sjy.js → editor.entity.(_sha)-Bnx7yUP0.js} +14 -14
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-oepecPae.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-CUobbQdQ.js → entity._sha.scenarios._scenarioId.dev-KTQuL0aj.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{manifest-5d53342d.js → manifest-3157d6b8.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-DcJSnBCE.js → analysisRunner-BMmkgAkg.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-CEaDhUiv.js → index-DxB0pOSt.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-DA7guOrE.js → init-DLYLaqqP.js} +2 -2
- package/codeyam-cli/src/webserver/build/server/assets/{server-build-juyiY2m6.js → server-build-CcyitQLQ.js} +111 -111
- 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/idleDetector.js +41 -8
- package/codeyam-cli/src/webserver/idleDetector.js.map +1 -1
- package/codeyam-cli/src/webserver/scripts/journalCapture.ts +36 -0
- package/codeyam-cli/src/webserver/terminalServer.js +4 -4
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/codeyam-editor-reference.md +214 -0
- package/package.json +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-CxmrE6AF.js +0 -41
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTimestamp": "2026-03-
|
|
3
|
-
"buildTime":
|
|
4
|
-
"gitCommit": "
|
|
2
|
+
"buildTimestamp": "2026-03-19T11:57:18.299Z",
|
|
3
|
+
"buildTime": 1773921438299,
|
|
4
|
+
"gitCommit": "471e1bd5c0e64ab79e5aae1965797f9cc293303d",
|
|
5
5
|
"nodeVersion": "v20.20.1",
|
|
6
6
|
"contentHash": "b046e014847d5b02d10d6795839ccd0d5117627cbd0be413260824610596a63d",
|
|
7
|
-
"buildNumber":
|
|
8
|
-
"semanticVersion": "0.1.
|
|
9
|
-
"version": "0.1.
|
|
7
|
+
"buildNumber": 1105,
|
|
8
|
+
"semanticVersion": "0.1.1105",
|
|
9
|
+
"version": "0.1.1105 (2026-03-19T11:57+b046e01)"
|
|
10
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
[3/
|
|
3
|
-
[3/
|
|
2
|
+
[3/19/2026, 11:57:18 AM] > codeyam-combo@1.0.0 mergeDependencies
|
|
3
|
+
[3/19/2026, 11:57:18 AM] > node ./scripts/mergePackageJsonFiles.cjs
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
[3/
|
|
6
|
+
[3/19/2026, 11:57:18 AM] Merged dependencies into root package.json
|
|
7
7
|
|
|
@@ -810,6 +810,7 @@ function printCycleOverview(root, state) {
|
|
|
810
810
|
console.log(chalk.green('Start now: ') + chalk.bold('codeyam editor 1'));
|
|
811
811
|
console.log(chalk.dim(' If the user already described what they want, pass it: codeyam editor 1 --prompt "their message"'));
|
|
812
812
|
}
|
|
813
|
+
console.log(chalk.dim('If stuck on CLI commands, scenarios, or debugging, read: .codeyam/docs/editor-reference.md'));
|
|
813
814
|
console.log();
|
|
814
815
|
}
|
|
815
816
|
// ─── Step 1: Plan ─────────────────────────────────────────────────────
|
|
@@ -2675,6 +2676,14 @@ async function handleRegister(jsonArg) {
|
|
|
2675
2676
|
console.log(chalk.red(` → ${err}`));
|
|
2676
2677
|
}
|
|
2677
2678
|
console.log(chalk.yellow(' The screenshot may show an error screen instead of the actual component.'));
|
|
2679
|
+
// Provide actionable debugging hints for HTTP/API errors
|
|
2680
|
+
const hasApiResponseError = data.clientErrors.some((e) => e.includes('API response error:'));
|
|
2681
|
+
const hasHttpError = data.clientErrors.some((e) => e.includes('HTTP error:'));
|
|
2682
|
+
if (hasHttpError || hasApiResponseError) {
|
|
2683
|
+
console.log(chalk.yellow(' To debug: look at the "API response error" lines above — they show the exact API endpoint'));
|
|
2684
|
+
console.log(chalk.yellow(' that failed and what the server returned. Then check the scenario seed data to ensure'));
|
|
2685
|
+
console.log(chalk.yellow(' all IDs referenced in the URL exist in the seed, and that the route is correct.'));
|
|
2686
|
+
}
|
|
2678
2687
|
console.log(chalk.yellow(' Fix the issue and re-register this scenario.'));
|
|
2679
2688
|
}
|
|
2680
2689
|
if (!res.ok) {
|
|
@@ -2700,6 +2709,53 @@ async function handleRegister(jsonArg) {
|
|
|
2700
2709
|
process.exit(1);
|
|
2701
2710
|
}
|
|
2702
2711
|
}
|
|
2712
|
+
// ─── Glossary-add subcommand ──────────────────────────────────────────
|
|
2713
|
+
/**
|
|
2714
|
+
* `codeyam editor glossary-add '{"name":"...", "filePath":"...", "description":"..."}'`
|
|
2715
|
+
*
|
|
2716
|
+
* Safely adds/updates entries in .codeyam/glossary.json via the CLI,
|
|
2717
|
+
* avoiding hand-editing that breaks on unicode characters.
|
|
2718
|
+
*/
|
|
2719
|
+
async function handleGlossaryAdd(jsonArg) {
|
|
2720
|
+
if (!jsonArg) {
|
|
2721
|
+
console.error(chalk.red('Error: JSON argument required.'));
|
|
2722
|
+
console.error(chalk.dim(' Usage: codeyam editor glossary-add \'{"name":"DrinkCard","filePath":"app/components/DrinkCard.tsx","description":"Displays a drink item"}\''));
|
|
2723
|
+
console.error(chalk.dim(' For large payloads: codeyam editor glossary-add @.codeyam/tmp/entry.json'));
|
|
2724
|
+
process.exit(1);
|
|
2725
|
+
}
|
|
2726
|
+
const parsed = parseRegisterArg(jsonArg);
|
|
2727
|
+
if (parsed.error) {
|
|
2728
|
+
console.error(chalk.red(`Error: ${parsed.error}`));
|
|
2729
|
+
process.exit(1);
|
|
2730
|
+
}
|
|
2731
|
+
// Normalize to array
|
|
2732
|
+
const items = Array.isArray(parsed.body) ? parsed.body : [parsed.body];
|
|
2733
|
+
// Read existing glossary
|
|
2734
|
+
const root = getProjectRoot();
|
|
2735
|
+
const glossaryPath = path.join(root, '.codeyam', 'glossary.json');
|
|
2736
|
+
let existing = [];
|
|
2737
|
+
try {
|
|
2738
|
+
const raw = JSON.parse(fs.readFileSync(glossaryPath, 'utf8'));
|
|
2739
|
+
existing = sanitizeGlossaryEntries(raw);
|
|
2740
|
+
}
|
|
2741
|
+
catch {
|
|
2742
|
+
// Glossary doesn't exist yet or can't be parsed — start fresh
|
|
2743
|
+
}
|
|
2744
|
+
// Merge
|
|
2745
|
+
const { validateGlossaryEntry, mergeGlossaryEntries } = await import('../utils/glossaryAdd.js');
|
|
2746
|
+
const result = mergeGlossaryEntries(existing, items);
|
|
2747
|
+
// Report validation errors
|
|
2748
|
+
for (const err of result.errors) {
|
|
2749
|
+
console.error(chalk.red(`Error at index ${err.index}: ${err.message}`));
|
|
2750
|
+
}
|
|
2751
|
+
if (result.added === 0 && result.updated === 0 && result.errors.length > 0) {
|
|
2752
|
+
process.exit(1);
|
|
2753
|
+
}
|
|
2754
|
+
// Write back with utf8 encoding to safely handle unicode
|
|
2755
|
+
fs.mkdirSync(path.dirname(glossaryPath), { recursive: true });
|
|
2756
|
+
fs.writeFileSync(glossaryPath, JSON.stringify(result.entries, null, 2), 'utf8');
|
|
2757
|
+
console.log(`added=${result.added} updated=${result.updated} total=${result.entries.length}`);
|
|
2758
|
+
}
|
|
2703
2759
|
// ─── Dependents subcommand ────────────────────────────────────────────
|
|
2704
2760
|
/**
|
|
2705
2761
|
* `codeyam editor dependents <EntityName>`
|
|
@@ -2988,22 +3044,62 @@ function printAuditGateFailures(data) {
|
|
|
2988
3044
|
if (!s)
|
|
2989
3045
|
return;
|
|
2990
3046
|
const issues = [];
|
|
2991
|
-
if (s.componentsMissing > 0)
|
|
3047
|
+
if (s.componentsMissing > 0) {
|
|
2992
3048
|
issues.push(`${s.componentsMissing} component(s) missing scenarios`);
|
|
2993
|
-
|
|
3049
|
+
const missing = (data.components || []).filter((c) => c.status === 'missing');
|
|
3050
|
+
for (const c of missing) {
|
|
3051
|
+
issues.push(` → ${c.name}${c.filePath ? ` (${c.filePath})` : ''}`);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
if (s.componentsWithErrors > 0) {
|
|
2994
3055
|
issues.push(`${s.componentsWithErrors} component(s) with client errors (browser API or runtime errors in captured scenarios)`);
|
|
2995
|
-
|
|
3056
|
+
const withErrors = (data.components || []).filter((c) => c.status === 'has_errors');
|
|
3057
|
+
for (const c of withErrors) {
|
|
3058
|
+
issues.push(` → ${c.name}${c.filePath ? ` (${c.filePath})` : ''}`);
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
if (s.functionsMissing > 0) {
|
|
2996
3062
|
issues.push(`${s.functionsMissing} function(s) missing test files`);
|
|
2997
|
-
|
|
3063
|
+
const missing = (data.functions || []).filter((f) => f.status === 'missing');
|
|
3064
|
+
for (const f of missing) {
|
|
3065
|
+
issues.push(` → ${f.name}${f.filePath ? ` (${f.filePath})` : ''}`);
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
if (s.functionsFailing > 0) {
|
|
2998
3069
|
issues.push(`${s.functionsFailing} function(s) with failing tests`);
|
|
2999
|
-
|
|
3070
|
+
const failing = (data.functions || []).filter((f) => f.status === 'failing');
|
|
3071
|
+
for (const f of failing) {
|
|
3072
|
+
issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
if (s.functionsRunnerError > 0) {
|
|
3000
3076
|
issues.push(`${s.functionsRunnerError} function(s) with test runner errors (the runner crashed — not a test failure)`);
|
|
3001
|
-
|
|
3077
|
+
const runnerErrors = (data.functions || []).filter((f) => f.status === 'runner_error');
|
|
3078
|
+
for (const f of runnerErrors) {
|
|
3079
|
+
issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
if (s.functionsNameMismatch > 0) {
|
|
3002
3083
|
issues.push(`${s.functionsNameMismatch} function(s) with test name mismatch`);
|
|
3084
|
+
const mismatch = (data.functions || []).filter((f) => f.status === 'name_mismatch');
|
|
3085
|
+
for (const f of mismatch) {
|
|
3086
|
+
issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3003
3089
|
if (s.missingFromGlossary > 0)
|
|
3004
3090
|
issues.push(`${s.missingFromGlossary} file(s) with scenarios not in glossary`);
|
|
3005
|
-
if (s.incompleteEntities > 0)
|
|
3006
|
-
|
|
3091
|
+
if (s.incompleteEntities > 0) {
|
|
3092
|
+
const preCount = s.preExistingIncompleteEntities || 0;
|
|
3093
|
+
if (preCount > 0 && preCount === s.incompleteEntities) {
|
|
3094
|
+
issues.push(`${s.incompleteEntities} entity/entities need import analysis (pre-existing — not caused by your current changes, but must be fixed before proceeding)`);
|
|
3095
|
+
}
|
|
3096
|
+
else if (preCount > 0) {
|
|
3097
|
+
issues.push(`${s.incompleteEntities} entity/entities need import analysis (${preCount} pre-existing — not from your changes)`);
|
|
3098
|
+
}
|
|
3099
|
+
else {
|
|
3100
|
+
issues.push(`${s.incompleteEntities} entity/entities need import analysis`);
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3007
3103
|
if (s.miscategorizedScenarios > 0)
|
|
3008
3104
|
issues.push(`${s.miscategorizedScenarios} component(s) using page URLs instead of isolation routes`);
|
|
3009
3105
|
if (s.scenariosNeedingRecapture > 0)
|
|
@@ -3083,6 +3179,11 @@ async function handleAudit() {
|
|
|
3083
3179
|
console.log();
|
|
3084
3180
|
// Components
|
|
3085
3181
|
if (components.length > 0) {
|
|
3182
|
+
// Build name frequency map for disambiguation
|
|
3183
|
+
const componentNameCounts = new Map();
|
|
3184
|
+
for (const c of components) {
|
|
3185
|
+
componentNameCounts.set(c.name, (componentNameCounts.get(c.name) || 0) + 1);
|
|
3186
|
+
}
|
|
3086
3187
|
console.log(chalk.bold('Components (scenarios):'));
|
|
3087
3188
|
for (const c of components) {
|
|
3088
3189
|
const icon = c.status === 'ok' ? chalk.green('✓') : chalk.red('✗');
|
|
@@ -3096,7 +3197,11 @@ async function handleAudit() {
|
|
|
3096
3197
|
else {
|
|
3097
3198
|
detail = chalk.red(' — no scenarios registered');
|
|
3098
3199
|
}
|
|
3099
|
-
|
|
3200
|
+
// Show file path for failing components always, for OK only when name is ambiguous
|
|
3201
|
+
const isDuplicate = (componentNameCounts.get(c.name) || 0) > 1;
|
|
3202
|
+
const showPath = c.status !== 'ok' || isDuplicate;
|
|
3203
|
+
const pathSuffix = showPath && c.filePath ? chalk.dim(` (${c.filePath})`) : '';
|
|
3204
|
+
console.log(` ${icon} ${c.name}${pathSuffix}${detail}`);
|
|
3100
3205
|
if (c.clientErrors && c.clientErrors.length > 0) {
|
|
3101
3206
|
for (const err of c.clientErrors.slice(0, 3)) {
|
|
3102
3207
|
console.log(chalk.red(` → ${err}`));
|
|
@@ -3211,6 +3316,19 @@ async function handleAudit() {
|
|
|
3211
3316
|
console.log(chalk.yellow(' Re-register these scenarios to capture updated screenshots.'));
|
|
3212
3317
|
console.log();
|
|
3213
3318
|
}
|
|
3319
|
+
// Duplicate glossary names (warning, not a failure)
|
|
3320
|
+
const duplicateNames = data.duplicateNames || [];
|
|
3321
|
+
if (duplicateNames.length > 0) {
|
|
3322
|
+
console.log(chalk.bold('Duplicate names in glossary (confusing for audit):'));
|
|
3323
|
+
for (const dn of duplicateNames) {
|
|
3324
|
+
console.log(` ${chalk.yellow('⚠')} "${dn.name}" appears ${dn.filePaths.length} times:`);
|
|
3325
|
+
for (const fp of dn.filePaths) {
|
|
3326
|
+
console.log(` ${fp}`);
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
console.log(chalk.yellow(' Fix: remove duplicate entries or rename them to be unique in .codeyam/glossary.json'));
|
|
3330
|
+
console.log();
|
|
3331
|
+
}
|
|
3214
3332
|
// Summary
|
|
3215
3333
|
const allOk = summary.allPassing;
|
|
3216
3334
|
if (allOk) {
|
|
@@ -3971,6 +4089,11 @@ const editorCommand = {
|
|
|
3971
4089
|
await handleRegister(argv.json || '');
|
|
3972
4090
|
return;
|
|
3973
4091
|
}
|
|
4092
|
+
// Subcommand: codeyam editor glossary-add '{"name":"...", ...}'
|
|
4093
|
+
if (argv.step === 'glossary-add') {
|
|
4094
|
+
await handleGlossaryAdd(argv.json || '');
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
3974
4097
|
// Subcommand: codeyam editor analyze-imports
|
|
3975
4098
|
if (argv.step === 'analyze-imports') {
|
|
3976
4099
|
await handleAnalyzeImports();
|