@codeyam/codeyam-cli 0.1.0-staging.ae0de75 → 0.1.0-staging.b8f4f94
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/package.json +3 -3
- package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +13 -7
- package/analyzer-template/packages/analyze/src/lib/asts/index.ts +7 -2
- package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js +196 -0
- package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js.map +1 -0
- package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js +114 -0
- package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js.map +1 -0
- package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js +149 -0
- package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js.map +1 -0
- package/codeyam-cli/src/commands/default.js +3 -46
- package/codeyam-cli/src/commands/default.js.map +1 -1
- package/codeyam-cli/src/commands/editor.js +254 -66
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +234 -0
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorJournal.test.js +12 -1
- package/codeyam-cli/src/utils/__tests__/editorJournal.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +29 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +1217 -0
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -0
- package/codeyam-cli/src/utils/backgroundServer.js +2 -2
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/editorAudit.js +45 -5
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorJournal.js +7 -0
- package/codeyam-cli/src/utils/editorJournal.js.map +1 -1
- package/codeyam-cli/src/utils/entityChangeStatus.js +255 -0
- package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -0
- package/codeyam-cli/src/utils/install-skills.js +1 -1
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +5 -1
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/Terminal-nZNBALox.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-diff-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/editor-DTwKl1Xu.js +10 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-D8ILZMR0.js → entity._sha.scenarios._scenarioId.dev-DjACbfdI.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/git-CdN8sCqs.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-h1-1oFYI.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-yHOVb4rc.js +15 -0
- package/codeyam-cli/src/webserver/build/client/assets/manifest-9422aeab.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{memory-FweZHj5U.js → memory-Dg0mvYrI.js} +4 -1
- package/codeyam-cli/src/webserver/build/client/assets/{root-DUKqhFlb.js → root-BzQgN2ff.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-BLhjL9Xi.js → index-Bh_pNxNA.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-Bqr22tlO.js +367 -0
- 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/server.js +32 -6
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +23 -4
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/editor-step-hook.py +53 -6
- package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +10 -5
- package/codeyam-cli/templates/skills/codeyam-memory/SKILL.md +10 -10
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.mjs +139 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.mjs +52 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/read-json-field.mjs +61 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/ripgrep-fallback.mjs +155 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.mjs +13 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter-session.mjs +95 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.mjs +160 -0
- package/package.json +10 -10
- package/packages/analyze/src/lib/ProjectAnalyzer.js +10 -4
- package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/asts/index.js +4 -2
- package/packages/analyze/src/lib/asts/index.js.map +1 -1
- package/scripts/npm-post-install.cjs +22 -0
- package/codeyam-cli/src/webserver/build/client/assets/Terminal-wkqC0AQk.js +0 -41
- package/codeyam-cli/src/webserver/build/client/assets/editor-CdjF_fX6.js +0 -8
- package/codeyam-cli/src/webserver/build/client/assets/git-CFCTYk9I.js +0 -15
- package/codeyam-cli/src/webserver/build/client/assets/globals-B17TBSS6.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-b8fd6b07.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-DyMuI5mU.js +0 -363
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.sh +0 -108
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.sh +0 -69
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.sh +0 -12
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter.jq +0 -45
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.sh +0 -139
|
@@ -8,6 +8,15 @@ import { ProgressReporter } from "../utils/progress.js";
|
|
|
8
8
|
import { initializeEnvironment } from "../utils/database.js";
|
|
9
9
|
import { loadEntities, loadAnalyses } from "../../../packages/database/index.js";
|
|
10
10
|
import { IS_INTERNAL_BUILD } from "../utils/buildFlags.js";
|
|
11
|
+
import { startBackgroundServer } from "../utils/backgroundServer.js";
|
|
12
|
+
import { installClaudeCodeSkills } from "../utils/install-skills.js";
|
|
13
|
+
import { setupClaudeCodeSettings } from "../utils/setupClaudeCodeSettings.js";
|
|
14
|
+
import { isAnalyzerFinalized, getAnalyzerTemplatePath, } from "../utils/analyzer.js";
|
|
15
|
+
import { updateProjectMetadata } from "../../../packages/database/index.js";
|
|
16
|
+
import { requireBranchAndProject, testEnvironment } from "../utils/database.js";
|
|
17
|
+
import { getProjectRoot as getStateProjectRoot } from "../state.js";
|
|
18
|
+
import { withoutSpinner, error as errorLog } from "../utils/progress.js";
|
|
19
|
+
import initCommand from "./init.js";
|
|
11
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
21
|
const __dirname = path.dirname(__filename);
|
|
13
22
|
const STEP_LABELS = {
|
|
@@ -23,6 +32,7 @@ const STEP_LABELS = {
|
|
|
23
32
|
10: 'Verify',
|
|
24
33
|
11: 'Journal',
|
|
25
34
|
12: 'Review',
|
|
35
|
+
13: 'Present',
|
|
26
36
|
};
|
|
27
37
|
/**
|
|
28
38
|
* Append a JSONL log entry to .codeyam/logs/editor-log.jsonl
|
|
@@ -122,13 +132,13 @@ function stepHeader(step, title, feature) {
|
|
|
122
132
|
console.log();
|
|
123
133
|
}
|
|
124
134
|
/**
|
|
125
|
-
* Print a colored progress tracker showing all
|
|
135
|
+
* Print a colored progress tracker showing all 13 steps.
|
|
126
136
|
* Steps before `current` are green ✓, `current` is bold cyan →, future steps are dim ○.
|
|
127
137
|
*/
|
|
128
138
|
function printProgressTracker(current) {
|
|
129
139
|
console.log();
|
|
130
140
|
console.log(chalk.dim('┌─────────────────────────────────────┐'));
|
|
131
|
-
for (let i = 1; i <=
|
|
141
|
+
for (let i = 1; i <= 13; i++) {
|
|
132
142
|
const label = STEP_LABELS[i];
|
|
133
143
|
const num = i < 10 ? ` ${i}` : `${i}`;
|
|
134
144
|
const content = `${num}. ${label.padEnd(28)}`;
|
|
@@ -166,7 +176,7 @@ function stopGate(current, opts) {
|
|
|
166
176
|
console.log(chalk.yellow('For the CURRENT step (→), show each checklist item with ✓ (done) or ✗ (skipped + reason).'));
|
|
167
177
|
console.log(chalk.yellow('If any items are ✗, explain why and ask if the user wants to address them.'));
|
|
168
178
|
console.log();
|
|
169
|
-
if (current <
|
|
179
|
+
if (current < 13) {
|
|
170
180
|
console.log(chalk.green('When done, run: ') +
|
|
171
181
|
chalk.bold(`codeyam editor ${current + 1}`));
|
|
172
182
|
}
|
|
@@ -210,7 +220,8 @@ function printResumptionHeader(step) {
|
|
|
210
220
|
`Check if a journal entry already exists for this feature:\n \`curl -s http://localhost:${port}/api/editor-journal\``,
|
|
211
221
|
'If an entry exists, use PATCH to update it — do NOT create a new one',
|
|
212
222
|
],
|
|
213
|
-
12: ['
|
|
223
|
+
12: ['Re-verify is safe to repeat — just re-run the checks'],
|
|
224
|
+
13: ['Check if commit already made:\n `git log --oneline -3`'],
|
|
214
225
|
};
|
|
215
226
|
const label = STEP_LABELS[step] || 'Unknown';
|
|
216
227
|
console.log(chalk.bold.yellow(`━━━ RESUMING Step ${step}: ${label} ━━━`));
|
|
@@ -315,7 +326,7 @@ function parseDebugTargets(target) {
|
|
|
315
326
|
}
|
|
316
327
|
if (entry.startsWith('step-')) {
|
|
317
328
|
const num = parseInt(entry.replace('step-', ''), 10);
|
|
318
|
-
if (!isNaN(num) && num >= 1 && num <=
|
|
329
|
+
if (!isNaN(num) && num >= 1 && num <= 13) {
|
|
319
330
|
valid.add(`step-${num}`);
|
|
320
331
|
continue;
|
|
321
332
|
}
|
|
@@ -428,7 +439,7 @@ function printCycleOverview(root, state) {
|
|
|
428
439
|
chalk.dim(' to start a new feature'));
|
|
429
440
|
}
|
|
430
441
|
else {
|
|
431
|
-
console.log('Each feature follows
|
|
442
|
+
console.log('Each feature follows 13 steps. You MUST run each command in order:');
|
|
432
443
|
console.log();
|
|
433
444
|
console.log(` ${chalk.bold.yellow(' 1')} ${chalk.bold('Plan')} — Plan the feature, confirm with user`);
|
|
434
445
|
console.log(` ${chalk.bold.yellow(' 2')} ${chalk.bold('Prototype')} — Build a working prototype fast`);
|
|
@@ -441,7 +452,8 @@ function printCycleOverview(root, state) {
|
|
|
441
452
|
console.log(` ${chalk.bold.yellow(' 9')} ${chalk.bold('User Scenarios')} — Create user-persona scenarios`);
|
|
442
453
|
console.log(` ${chalk.bold.yellow('10')} ${chalk.bold('Verify')} — Review screenshots, check for errors`);
|
|
443
454
|
console.log(` ${chalk.bold.yellow('11')} ${chalk.bold('Journal')} — Create/update journal entry`);
|
|
444
|
-
console.log(` ${chalk.bold.yellow('12')} ${chalk.bold('Review')} —
|
|
455
|
+
console.log(` ${chalk.bold.yellow('12')} ${chalk.bold('Review')} — Verify screenshots and audit`);
|
|
456
|
+
console.log(` ${chalk.bold.yellow('13')} ${chalk.bold('Present')} — Present summary, get approval`);
|
|
445
457
|
console.log();
|
|
446
458
|
console.log(chalk.green('Start now: ') + chalk.bold('codeyam editor 1'));
|
|
447
459
|
}
|
|
@@ -582,7 +594,8 @@ function printStep2(root, feature) {
|
|
|
582
594
|
console.log(chalk.dim(' Should look like: "startCommand": { "command": "sh", "args": ["-c", "npm run dev -- --port $PORT"] }'));
|
|
583
595
|
console.log(chalk.dim(' If missing, add it manually. $PORT is replaced at runtime by the analyzer.'));
|
|
584
596
|
console.log();
|
|
585
|
-
checkbox(`
|
|
597
|
+
checkbox(`Detect the new project: \`curl -s -X POST http://localhost:${port}/api/editor-refresh\``);
|
|
598
|
+
console.log(chalk.dim(' This re-detects webapps and auto-starts the dev server.'));
|
|
586
599
|
console.log();
|
|
587
600
|
console.log(chalk.bold('Build the feature:'));
|
|
588
601
|
}
|
|
@@ -601,7 +614,7 @@ function printStep2(root, feature) {
|
|
|
601
614
|
console.log(chalk.yellow(' Verify everything works before presenting the prototype to the user.'));
|
|
602
615
|
checkbox('Verify the page loads: curl the dev server URL and confirm HTTP 200 (not an error page)');
|
|
603
616
|
checkbox('Verify API routes return valid JSON: curl each route and confirm no error responses');
|
|
604
|
-
checkbox('Check for broken images:
|
|
617
|
+
checkbox('Check for broken images: extract <img> src URLs from the HTML, then `curl -I <url>` each one and confirm HTTP 200 (not 404/403)');
|
|
605
618
|
checkbox('Check the dev server terminal output for runtime errors (missing modules, failed imports)');
|
|
606
619
|
console.log(chalk.dim(' If any check fails, fix the issue and re-verify before proceeding.'));
|
|
607
620
|
console.log();
|
|
@@ -629,19 +642,16 @@ function printStep3(root, feature) {
|
|
|
629
642
|
console.log('Summarize what was built and get user confirmation.');
|
|
630
643
|
console.log();
|
|
631
644
|
console.log(chalk.bold('Before presenting — verify everything works:'));
|
|
632
|
-
checkbox(`Refresh the preview: \`curl -s -X POST http://localhost:${port}/api/
|
|
633
|
-
checkbox(`Refresh and check for SSR errors: \`curl -s -X POST http://localhost:${port}/api/dev-mode-preview\` — look at the \`preview\` field for \`healthy: false\``);
|
|
645
|
+
checkbox(`Refresh the preview: \`curl -s -X POST http://localhost:${port}/api/dev-mode-preview\` — check the \`preview\` field for \`healthy: false\``);
|
|
634
646
|
checkbox('Verify API routes return valid data (curl each route)');
|
|
635
|
-
checkbox(`Navigate to each page and check health: \`curl -s -X POST http://localhost:${port}/api/dev-mode-preview -H 'Content-Type: application/json' -d '{"path":"/your-route"}'\``);
|
|
636
647
|
console.log();
|
|
637
|
-
console.log(chalk.bold('
|
|
638
|
-
checkbox('Get the dev server URL
|
|
648
|
+
console.log(chalk.bold.red(' Verify EVERY image loads (this is the #1 source of broken prototypes):'));
|
|
649
|
+
checkbox('Get the dev server URL: `curl -s http://localhost:' +
|
|
639
650
|
port +
|
|
640
|
-
'/api/editor-dev-server`
|
|
641
|
-
checkbox(
|
|
642
|
-
checkbox('
|
|
643
|
-
checkbox('
|
|
644
|
-
console.log(chalk.yellow(' Do not present to the user until all checks pass. Fix issues first.'));
|
|
651
|
+
'/api/editor-dev-server` → use the `url` field');
|
|
652
|
+
checkbox("Curl each page's HTML and extract every `<img>` src URL");
|
|
653
|
+
checkbox('HTTP-fetch EVERY image URL: `curl -s -o /dev/null -w "%{http_code}" <url>` — each must return 200');
|
|
654
|
+
checkbox('Fix or remove any image that returns non-200 before continuing');
|
|
645
655
|
console.log();
|
|
646
656
|
console.log(chalk.bold('Then present to the user:'));
|
|
647
657
|
checkbox('Summarize what was built (routes, components, data)');
|
|
@@ -952,13 +962,13 @@ function printStep10(root, feature) {
|
|
|
952
962
|
console.log(chalk.dim(` codeyam editor register '{"name":"ComponentName - Scenario",...}'`));
|
|
953
963
|
console.log();
|
|
954
964
|
console.log(chalk.bold('Editor scenarios (App tab) — visual + error check:'));
|
|
955
|
-
checkbox(`Refresh the preview: \`curl -s -X POST http://localhost:${port}/api/
|
|
965
|
+
checkbox(`Refresh the preview: \`curl -s -X POST http://localhost:${port}/api/dev-mode-preview\``);
|
|
956
966
|
checkbox('Click through each app-level and user-persona scenario in the preview');
|
|
957
967
|
checkbox(`Check for client-side errors: \`curl -s http://localhost:${port}/api/editor-client-errors\``);
|
|
958
968
|
console.log(chalk.yellow(' If `hasErrors` is true: list each scenario with errors, fix the source code,'));
|
|
959
969
|
console.log(chalk.yellow(' re-register the affected scenarios, and re-check until hasErrors is false'));
|
|
960
970
|
console.log(chalk.dim(' Common errors: React errors, failed fetches, undefined references, hydration mismatches'));
|
|
961
|
-
checkbox('Verify no broken images
|
|
971
|
+
checkbox('Verify no broken images: extract <img> src URLs from each page, `curl -s -o /dev/null -w "%{http_code}" <url>` each one — must return 200');
|
|
962
972
|
console.log();
|
|
963
973
|
console.log(chalk.bold('Library functions — test check:'));
|
|
964
974
|
checkbox('Re-run all test files from step 5 to confirm they still pass');
|
|
@@ -995,12 +1005,13 @@ function printStep11(root, feature) {
|
|
|
995
1005
|
console.log(chalk.dim(` -H 'Content-Type: application/json' \\`));
|
|
996
1006
|
console.log(chalk.dim(` -d '{"title":"...","type":"feature","description":"...","includeSessionScenarios":true}'`));
|
|
997
1007
|
console.log(chalk.dim(' includeSessionScenarios auto-discovers component + app + user persona screenshots'));
|
|
998
|
-
checkbox(`Returning
|
|
1008
|
+
checkbox(`Returning to step 11 (before commit) — update the existing journal entry:`);
|
|
999
1009
|
console.log(chalk.dim(` curl -s -X PATCH http://localhost:${port}/api/editor-journal-update \\`));
|
|
1000
1010
|
console.log(chalk.dim(` -H 'Content-Type: application/json' \\`));
|
|
1001
1011
|
console.log(chalk.dim(` -d '{"time":"<journal entry time>","description":"<updated>","includeSessionScenarios":true}'`));
|
|
1012
|
+
console.log(chalk.dim(' Note: PATCH only works before the entry is committed. After commit, use POST to create a new entry.'));
|
|
1002
1013
|
console.log();
|
|
1003
|
-
console.log(chalk.dim('Focus on creating or updating the journal entry. Summary and
|
|
1014
|
+
console.log(chalk.dim('Focus on creating or updating the journal entry. Summary and presentation happen in step 13.'));
|
|
1004
1015
|
stopGate(11);
|
|
1005
1016
|
}
|
|
1006
1017
|
// ─── Step 12: Review ──────────────────────────────────────────────────
|
|
@@ -1021,9 +1032,9 @@ function printStep12(root, feature) {
|
|
|
1021
1032
|
if (isResuming) {
|
|
1022
1033
|
printResumptionHeader(12);
|
|
1023
1034
|
}
|
|
1024
|
-
console.log('Verify
|
|
1035
|
+
console.log('Verify all screenshots and checks pass before presenting to the user.');
|
|
1025
1036
|
console.log();
|
|
1026
|
-
console.log(chalk.bold('
|
|
1037
|
+
console.log(chalk.bold('Checklist (do all of this silently):'));
|
|
1027
1038
|
checkbox(`Refresh the preview: \`curl -s -X POST http://localhost:${port}/api/dev-mode-preview\``);
|
|
1028
1039
|
checkbox('Verify each component has screenshots in the App tab (grouped under Components)');
|
|
1029
1040
|
checkbox('If any are missing, re-register them using `codeyam editor register`');
|
|
@@ -1031,42 +1042,62 @@ function printStep12(root, feature) {
|
|
|
1031
1042
|
checkbox('If `hasErrors` is true, fix them and re-capture affected scenarios');
|
|
1032
1043
|
checkbox('Run `codeyam editor audit` to verify completeness of scenarios and tests');
|
|
1033
1044
|
checkbox('Do not proceed until all checks pass');
|
|
1045
|
+
stopGate(12);
|
|
1046
|
+
}
|
|
1047
|
+
// ─── Step 13: Present ─────────────────────────────────────────────────
|
|
1048
|
+
function printStep13(root, feature) {
|
|
1049
|
+
const port = getServerPort();
|
|
1050
|
+
const prevState = readState(root);
|
|
1051
|
+
const isResuming = prevState?.step === 13;
|
|
1052
|
+
const now = new Date().toISOString();
|
|
1053
|
+
writeState(root, {
|
|
1054
|
+
feature,
|
|
1055
|
+
step: 13,
|
|
1056
|
+
label: STEP_LABELS[13],
|
|
1057
|
+
startedAt: isResuming ? prevState.startedAt : now,
|
|
1058
|
+
featureStartedAt: prevState?.featureStartedAt || now,
|
|
1059
|
+
});
|
|
1060
|
+
logEvent(root, 'step', { step: 13, label: 'Present', feature });
|
|
1061
|
+
stepHeader(13, 'Present', feature);
|
|
1062
|
+
if (isResuming) {
|
|
1063
|
+
printResumptionHeader(13);
|
|
1064
|
+
}
|
|
1065
|
+
console.log('Present the results to the user and get their approval.');
|
|
1034
1066
|
console.log();
|
|
1035
|
-
console.log(chalk.bold('
|
|
1036
|
-
checkbox(
|
|
1037
|
-
checkbox('
|
|
1038
|
-
checkbox('Switch the
|
|
1067
|
+
console.log(chalk.bold('Checklist:'));
|
|
1068
|
+
checkbox(`Fetch all scenarios: \`curl -s http://localhost:${port}/api/editor-scenarios\``);
|
|
1069
|
+
checkbox('Pick the scenario that best showcases the feature (happy path, most visually complete)');
|
|
1070
|
+
checkbox('Switch the preview to that scenario using its `id`:');
|
|
1039
1071
|
console.log(chalk.dim(` curl -s -X POST http://localhost:${port}/api/dev-mode-preview \\`));
|
|
1040
|
-
console.log(chalk.dim(` -H 'Content-Type: application/json' -d '{"
|
|
1072
|
+
console.log(chalk.dim(` -H 'Content-Type: application/json' -d '{"scenarioId":"<id>"}'`));
|
|
1041
1073
|
checkbox(`Show the results panel: \`curl -s -X POST http://localhost:${port}/api/editor-show-results\``);
|
|
1042
1074
|
console.log(chalk.dim(' This opens a visual panel below the terminal showing all scenarios with screenshots.'));
|
|
1043
1075
|
console.log(chalk.dim(' The user can click scenarios to switch the live preview.'));
|
|
1076
|
+
checkbox('Write a 1-2 sentence summary of what was built');
|
|
1077
|
+
checkbox('Report test count and audit status (one line)');
|
|
1044
1078
|
console.log();
|
|
1045
|
-
console.log(chalk.bold('
|
|
1079
|
+
console.log(chalk.bold('Present a selection menu to the user (use AskUserQuestion):'));
|
|
1046
1080
|
console.log(chalk.green(' "Save & commit"') +
|
|
1047
1081
|
chalk.dim(' — git commit all changes and record in journal'));
|
|
1048
1082
|
console.log(chalk.yellow(' "I\'d like to make some changes"') +
|
|
1049
1083
|
chalk.dim(' — describe changes, then re-verify'));
|
|
1050
1084
|
console.log();
|
|
1051
1085
|
console.log(chalk.bold('If the user chooses "Save & commit":'));
|
|
1086
|
+
checkbox(`Hide the results panel first: \`curl -s -X POST http://localhost:${port}/api/editor-hide-results\``);
|
|
1052
1087
|
checkbox(`Git commit using the journal description: \`curl -s -X POST http://localhost:${port}/api/editor-commit -H 'Content-Type: application/json' -d '{"message":"feat: <title>\\n\\n<journal description>"}'\``);
|
|
1053
1088
|
console.log(chalk.dim(' The commit message body MUST match the journal description exactly'));
|
|
1054
1089
|
checkbox(`Update journal with commit SHA: \`curl -s -X PATCH http://localhost:${port}/api/editor-journal-update -H 'Content-Type: application/json' -d '{"time":"<journal entry time>","commitSha":"<sha>","commitMessage":"feat: <title>"}'\``);
|
|
1055
1090
|
console.log(chalk.green(' Then run: ') +
|
|
1056
|
-
chalk.bold('codeyam editor
|
|
1091
|
+
chalk.bold('codeyam editor steps') +
|
|
1057
1092
|
chalk.green(' to start the next feature'));
|
|
1058
1093
|
console.log();
|
|
1059
|
-
console.log(chalk.bold('If the user chooses "Make changes":'));
|
|
1060
|
-
checkbox(
|
|
1061
|
-
checkbox('
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
console.log(chalk.red.bold(' IMPORTANT: You MUST run the change command. Do not skip this or try to re-verify manually.'));
|
|
1067
|
-
console.log();
|
|
1068
|
-
console.log(chalk.dim('Complete all phases in order: summary, screenshot verification, user menu.'));
|
|
1069
|
-
stopGate(12, { confirm: true });
|
|
1094
|
+
console.log(chalk.bold('If the user chooses "Make changes" (or asks for ANY change, even as a question):'));
|
|
1095
|
+
checkbox(`Hide the results panel: \`curl -s -X POST http://localhost:${port}/api/editor-hide-results\``);
|
|
1096
|
+
checkbox('Ask what changes the user wants (if not already clear)');
|
|
1097
|
+
checkbox(`Run: \`codeyam editor change "${feature}"\` — this gives you the change checklist`);
|
|
1098
|
+
checkbox('THEN make the requested changes and follow the checklist');
|
|
1099
|
+
console.log(chalk.red.bold(' IMPORTANT: Always run the change command BEFORE writing any code.'));
|
|
1100
|
+
stopGate(13, { confirm: true });
|
|
1070
1101
|
}
|
|
1071
1102
|
// ─── Command definition ───────────────────────────────────────────────
|
|
1072
1103
|
// ─── Analyze-imports subcommand ────────────────────────────────────────
|
|
@@ -1334,7 +1365,7 @@ async function handleDependents(entityName) {
|
|
|
1334
1365
|
* Prints a condensed post-change checklist that guides Claude through
|
|
1335
1366
|
* re-verifying after user-requested modifications. This is the "change
|
|
1336
1367
|
* loop" — it replaces the freeform "make changes" path with structured
|
|
1337
|
-
* instructions that always loop back to step
|
|
1368
|
+
* instructions that always loop back to step 13 present.
|
|
1338
1369
|
*/
|
|
1339
1370
|
function handleChange(feature) {
|
|
1340
1371
|
const root = getProjectRoot();
|
|
@@ -1357,6 +1388,9 @@ function handleChange(feature) {
|
|
|
1357
1388
|
console.log();
|
|
1358
1389
|
console.log('The user has requested changes. Follow this checklist after making them.');
|
|
1359
1390
|
console.log();
|
|
1391
|
+
console.log(chalk.bold('0. Close the results panel:'));
|
|
1392
|
+
checkbox(`Hide results: \`curl -s -X POST http://localhost:${port}/api/editor-hide-results\``);
|
|
1393
|
+
console.log();
|
|
1360
1394
|
console.log(chalk.bold('1. Re-register affected component scenarios:'));
|
|
1361
1395
|
checkbox('For each component you modified, re-register ALL its scenarios');
|
|
1362
1396
|
console.log(chalk.dim(` codeyam editor register '{"name":"ComponentName - ScenarioName","description":"...","componentName":"ComponentName","componentPath":"app/components/ComponentName.tsx"}'`));
|
|
@@ -1378,13 +1412,13 @@ function handleChange(feature) {
|
|
|
1378
1412
|
checkbox(`Check for client-side errors: \`curl -s http://localhost:${port}/api/editor-client-errors\``);
|
|
1379
1413
|
checkbox('Fix any errors, then re-register affected scenarios');
|
|
1380
1414
|
console.log();
|
|
1381
|
-
console.log(chalk.bold('5.
|
|
1382
|
-
checkbox(`
|
|
1383
|
-
console.log(chalk.dim('
|
|
1415
|
+
console.log(chalk.bold('5. Create a new journal entry for this change:'));
|
|
1416
|
+
checkbox(`Create journal entry: \`curl -s -X POST http://localhost:${port}/api/editor-journal-entry -H 'Content-Type: application/json' -d '{"title":"...","type":"feature","description":"<describe what changed>","includeSessionScenarios":true}'\``);
|
|
1417
|
+
console.log(chalk.dim(' Do NOT PATCH the previous entry — it is frozen after commit. Always POST a new one.'));
|
|
1384
1418
|
console.log();
|
|
1385
1419
|
console.log(chalk.bold.green('When all checks pass, run: ') +
|
|
1386
|
-
chalk.bold(`codeyam editor
|
|
1387
|
-
console.log(chalk.dim(' This
|
|
1420
|
+
chalk.bold(`codeyam editor 13`));
|
|
1421
|
+
console.log(chalk.dim(' This enters the present step to show the updated results to the user.'));
|
|
1388
1422
|
console.log();
|
|
1389
1423
|
}
|
|
1390
1424
|
// ─── Audit subcommand ────────────────────────────────────────────────
|
|
@@ -1433,11 +1467,24 @@ async function handleAudit() {
|
|
|
1433
1467
|
console.log(chalk.bold('Functions (test files):'));
|
|
1434
1468
|
for (const f of functions) {
|
|
1435
1469
|
const icon = f.status === 'ok' ? chalk.green('✓') : chalk.red('✗');
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
:
|
|
1439
|
-
|
|
1440
|
-
|
|
1470
|
+
let detail;
|
|
1471
|
+
switch (f.status) {
|
|
1472
|
+
case 'ok':
|
|
1473
|
+
detail = chalk.dim(` (${f.testFile})`);
|
|
1474
|
+
break;
|
|
1475
|
+
case 'failing':
|
|
1476
|
+
detail = chalk.red(` — tests failing: ${f.testFile}`);
|
|
1477
|
+
break;
|
|
1478
|
+
case 'name_mismatch':
|
|
1479
|
+
detail = chalk.red(` — tests pass but missing top-level describe("${f.name}", ...) — tests won't display in UI`);
|
|
1480
|
+
break;
|
|
1481
|
+
case 'missing':
|
|
1482
|
+
default:
|
|
1483
|
+
detail = f.testFile
|
|
1484
|
+
? chalk.red(` — test file missing: ${f.testFile}`)
|
|
1485
|
+
: chalk.red(' — no test file specified');
|
|
1486
|
+
break;
|
|
1487
|
+
}
|
|
1441
1488
|
console.log(` ${icon} ${f.name}${detail}`);
|
|
1442
1489
|
}
|
|
1443
1490
|
console.log();
|
|
@@ -1456,6 +1503,12 @@ async function handleAudit() {
|
|
|
1456
1503
|
if (summary.functionsMissing > 0) {
|
|
1457
1504
|
parts.push(`${summary.functionsMissing} function${summary.functionsMissing !== 1 ? 's' : ''} missing tests`);
|
|
1458
1505
|
}
|
|
1506
|
+
if (summary.functionsFailing > 0) {
|
|
1507
|
+
parts.push(`${summary.functionsFailing} function${summary.functionsFailing !== 1 ? 's' : ''} with failing tests`);
|
|
1508
|
+
}
|
|
1509
|
+
if (summary.functionsNameMismatch > 0) {
|
|
1510
|
+
parts.push(`${summary.functionsNameMismatch} function${summary.functionsNameMismatch !== 1 ? 's' : ''} with test name mismatch (missing top-level describe)`);
|
|
1511
|
+
}
|
|
1459
1512
|
console.log(chalk.red.bold('Audit failed: ') + parts.join(', '));
|
|
1460
1513
|
}
|
|
1461
1514
|
console.log();
|
|
@@ -1611,8 +1664,9 @@ function handleEditorDebug(args) {
|
|
|
1611
1664
|
10: printStep10,
|
|
1612
1665
|
11: printStep11,
|
|
1613
1666
|
12: printStep12,
|
|
1667
|
+
13: printStep13,
|
|
1614
1668
|
};
|
|
1615
|
-
for (let step = 1; step <=
|
|
1669
|
+
for (let step = 1; step <= 13; step++) {
|
|
1616
1670
|
const stepId = `step-${step}`;
|
|
1617
1671
|
if (!wants(stepId))
|
|
1618
1672
|
continue;
|
|
@@ -1691,8 +1745,8 @@ const editorCommand = {
|
|
|
1691
1745
|
describe: 'Editor mode guided workflow',
|
|
1692
1746
|
builder: (yargs) => {
|
|
1693
1747
|
const stepDescription = IS_INTERNAL_BUILD
|
|
1694
|
-
? 'Step number (1-
|
|
1695
|
-
: 'Step number (1-
|
|
1748
|
+
? 'Step number (1-13) or subcommand (register, analyze-imports, dependents, audit, scenarios, change, debug)'
|
|
1749
|
+
: 'Step number (1-13) or subcommand (register, analyze-imports, dependents, audit, scenarios, change)';
|
|
1696
1750
|
let builder = yargs
|
|
1697
1751
|
.positional('step', {
|
|
1698
1752
|
type: 'string',
|
|
@@ -1705,12 +1759,18 @@ const editorCommand = {
|
|
|
1705
1759
|
.option('feature', {
|
|
1706
1760
|
type: 'string',
|
|
1707
1761
|
describe: 'Feature name (required for step 2)',
|
|
1762
|
+
})
|
|
1763
|
+
.option('port', {
|
|
1764
|
+
type: 'number',
|
|
1765
|
+
alias: 'p',
|
|
1766
|
+
describe: 'Port to run the web server on',
|
|
1767
|
+
default: 3111,
|
|
1708
1768
|
});
|
|
1709
1769
|
if (IS_INTERNAL_BUILD) {
|
|
1710
1770
|
builder = builder
|
|
1711
1771
|
.option('target', {
|
|
1712
1772
|
type: 'string',
|
|
1713
|
-
describe: 'Debug target (setup, overview, overview-with-state, step-1..step-
|
|
1773
|
+
describe: 'Debug target (setup, overview, overview-with-state, step-1..step-13, or comma-separated list)',
|
|
1714
1774
|
})
|
|
1715
1775
|
.option('resume', {
|
|
1716
1776
|
type: 'boolean',
|
|
@@ -1769,13 +1829,8 @@ const editorCommand = {
|
|
|
1769
1829
|
await handleEditorDebug(argv);
|
|
1770
1830
|
return;
|
|
1771
1831
|
}
|
|
1772
|
-
|
|
1773
|
-
if (step
|
|
1774
|
-
console.error(chalk.red(`Error: Invalid step "${argv.step}". Must be 1-12.`));
|
|
1775
|
-
process.exit(1);
|
|
1776
|
-
}
|
|
1777
|
-
if (step == null) {
|
|
1778
|
-
// No step specified: setup or overview
|
|
1832
|
+
// Subcommand: codeyam editor steps — show setup or cycle overview
|
|
1833
|
+
if (argv.step === 'steps') {
|
|
1779
1834
|
if (!hasProject(root)) {
|
|
1780
1835
|
printSetup(root);
|
|
1781
1836
|
}
|
|
@@ -1785,6 +1840,137 @@ const editorCommand = {
|
|
|
1785
1840
|
}
|
|
1786
1841
|
return;
|
|
1787
1842
|
}
|
|
1843
|
+
const step = argv.step ? parseInt(argv.step, 10) : undefined;
|
|
1844
|
+
if (step != null && (isNaN(step) || step < 1 || step > 13)) {
|
|
1845
|
+
console.error(chalk.red(`Error: Invalid step "${argv.step}". Must be 1-13.`));
|
|
1846
|
+
process.exit(1);
|
|
1847
|
+
}
|
|
1848
|
+
if (step == null) {
|
|
1849
|
+
// No step specified: launch editor server + open browser
|
|
1850
|
+
// Auto-init if needed
|
|
1851
|
+
let projectRoot = getStateProjectRoot();
|
|
1852
|
+
if (!projectRoot) {
|
|
1853
|
+
await initCommand.handler({
|
|
1854
|
+
force: false,
|
|
1855
|
+
autoInit: true,
|
|
1856
|
+
$0: '',
|
|
1857
|
+
_: [],
|
|
1858
|
+
});
|
|
1859
|
+
projectRoot = getStateProjectRoot();
|
|
1860
|
+
if (!projectRoot) {
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
const configPath = path.join(projectRoot, '.codeyam', 'config.json');
|
|
1865
|
+
try {
|
|
1866
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
1867
|
+
const { projectSlug } = config;
|
|
1868
|
+
if (!projectSlug) {
|
|
1869
|
+
errorLog('Missing project slug. Try reinitializing with: codeyam init --force');
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
const connectionOk = await withoutSpinner(() => testEnvironment());
|
|
1873
|
+
if (!connectionOk) {
|
|
1874
|
+
errorLog('Environment validation failed');
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
const { project, branch } = await requireBranchAndProject(projectSlug);
|
|
1878
|
+
// `codeyam editor` (no step) always implies editor mode.
|
|
1879
|
+
// The empty-folder heuristic is no longer needed here — running this
|
|
1880
|
+
// command IS the signal. We still detect empty folders so that
|
|
1881
|
+
// the very first `codeyam editor` in a bare directory works before
|
|
1882
|
+
// metadata has been persisted.
|
|
1883
|
+
const editorMode = true;
|
|
1884
|
+
if (editorMode && !project.metadata?.labs?.simulations) {
|
|
1885
|
+
try {
|
|
1886
|
+
await updateProjectMetadata({
|
|
1887
|
+
projectSlug,
|
|
1888
|
+
metadataUpdate: {
|
|
1889
|
+
editorMode: true,
|
|
1890
|
+
labs: { simulations: true },
|
|
1891
|
+
},
|
|
1892
|
+
});
|
|
1893
|
+
const refreshed = await requireBranchAndProject(projectSlug);
|
|
1894
|
+
Object.assign(project, refreshed.project);
|
|
1895
|
+
}
|
|
1896
|
+
catch {
|
|
1897
|
+
// Non-fatal
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
// Install skills/hooks
|
|
1901
|
+
const simulationsEnabled = project.metadata?.labs?.simulations ?? false;
|
|
1902
|
+
const skillMode = simulationsEnabled
|
|
1903
|
+
? 'full'
|
|
1904
|
+
: editorMode
|
|
1905
|
+
? 'editor'
|
|
1906
|
+
: 'memory';
|
|
1907
|
+
await installClaudeCodeSkills(projectRoot, {
|
|
1908
|
+
mode: skillMode,
|
|
1909
|
+
editorMode,
|
|
1910
|
+
});
|
|
1911
|
+
setupClaudeCodeSettings(projectRoot, {
|
|
1912
|
+
mode: skillMode,
|
|
1913
|
+
editorMode,
|
|
1914
|
+
});
|
|
1915
|
+
// Auto-finalize analyzer so codeyam analyze works
|
|
1916
|
+
if (editorMode && !isAnalyzerFinalized()) {
|
|
1917
|
+
try {
|
|
1918
|
+
const { execSync } = await import('child_process');
|
|
1919
|
+
const templatePath = getAnalyzerTemplatePath();
|
|
1920
|
+
if (fs.existsSync(templatePath)) {
|
|
1921
|
+
console.log(' Setting up simulations (first time only)...');
|
|
1922
|
+
execSync('npm install --include=dev', {
|
|
1923
|
+
cwd: templatePath,
|
|
1924
|
+
stdio: 'pipe',
|
|
1925
|
+
});
|
|
1926
|
+
execSync('npx playwright install chromium', {
|
|
1927
|
+
cwd: templatePath,
|
|
1928
|
+
stdio: 'pipe',
|
|
1929
|
+
});
|
|
1930
|
+
execSync('npm run build', {
|
|
1931
|
+
cwd: templatePath,
|
|
1932
|
+
stdio: 'pipe',
|
|
1933
|
+
});
|
|
1934
|
+
fs.writeFileSync(path.join(templatePath, '.finalized'), new Date().toISOString());
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
catch {
|
|
1938
|
+
// Non-fatal
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
// Start background server
|
|
1942
|
+
const { url } = await startBackgroundServer({
|
|
1943
|
+
port: argv.port || 3111,
|
|
1944
|
+
rootPath: projectRoot,
|
|
1945
|
+
project,
|
|
1946
|
+
branch,
|
|
1947
|
+
});
|
|
1948
|
+
console.log();
|
|
1949
|
+
console.log(` Dashboard: ${url}`);
|
|
1950
|
+
console.log(' Run "codeyam --help" for all commands');
|
|
1951
|
+
console.log(chalk.bold(' Run "codeyam editor" to launch the editor at any time'));
|
|
1952
|
+
console.log();
|
|
1953
|
+
// Open browser to /editor
|
|
1954
|
+
try {
|
|
1955
|
+
const { execSync } = await import('child_process');
|
|
1956
|
+
const openCommand = process.platform === 'darwin'
|
|
1957
|
+
? 'open'
|
|
1958
|
+
: process.platform === 'win32'
|
|
1959
|
+
? 'start ""'
|
|
1960
|
+
: 'xdg-open';
|
|
1961
|
+
execSync(`${openCommand} "${url}/editor"`, { stdio: 'ignore' });
|
|
1962
|
+
}
|
|
1963
|
+
catch {
|
|
1964
|
+
// Silently fail if open command doesn't work
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
catch (err) {
|
|
1968
|
+
errorLog('Failed to start CodeYam editor server');
|
|
1969
|
+
errorLog(err);
|
|
1970
|
+
process.exit(1);
|
|
1971
|
+
}
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1788
1974
|
const state = readState(root);
|
|
1789
1975
|
switch (step) {
|
|
1790
1976
|
case 1: {
|
|
@@ -1811,7 +1997,8 @@ const editorCommand = {
|
|
|
1811
1997
|
case 9:
|
|
1812
1998
|
case 10:
|
|
1813
1999
|
case 11:
|
|
1814
|
-
case 12:
|
|
2000
|
+
case 12:
|
|
2001
|
+
case 13: {
|
|
1815
2002
|
const feature = argv.feature || state?.feature;
|
|
1816
2003
|
if (!feature) {
|
|
1817
2004
|
console.error(chalk.red('Error: No feature in progress. Run codeyam editor 1 first.'));
|
|
@@ -1828,6 +2015,7 @@ const editorCommand = {
|
|
|
1828
2015
|
10: printStep10,
|
|
1829
2016
|
11: printStep11,
|
|
1830
2017
|
12: printStep12,
|
|
2018
|
+
13: printStep13,
|
|
1831
2019
|
};
|
|
1832
2020
|
stepFns[step](root, feature);
|
|
1833
2021
|
break;
|