@codeyam/codeyam-cli 0.1.0-staging.dbc742d → 0.1.0-staging.e057775
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/__tests__/editor.stepDispatch.test.js +45 -0
- package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js.map +1 -0
- package/codeyam-cli/src/commands/editor.js +177 -80
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js +144 -0
- package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +221 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +51 -1
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +14 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/analyzerFinalization.js +96 -0
- package/codeyam-cli/src/utils/analyzerFinalization.js.map +1 -0
- package/codeyam-cli/src/utils/editorAudit.js +17 -0
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorPreview.js +26 -0
- package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarios.js +4 -0
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +17 -0
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/git.js +3 -2
- package/codeyam-cli/src/webserver/app/lib/git.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-0DY_NKil.js → ScenarioViewer-Bd-hxofb.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-Csi0_PMl.js → dev.empty-BsDh6TSF.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor-PBc_6L9R.js +10 -0
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-4FzHlcNn.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BF4oLwaE.js → entity._sha._-BsDXNp45.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-C7YX6r3H.js → entity._sha.scenarios._scenarioId.dev-BgAqUtTZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-Bmshgrij.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-B8vTTNy2.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/manifest-65850841.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{root-CHOdrM6Y.js → root-BwX8YgFb.js} +8 -8
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-BE43Hjti.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/{index-BWoRb5RY.js → index-DEEQf4pi.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-DbChSUQP.js → init-CkWmyFY2.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BHi-9O8W.js +439 -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/editorProxy.js +26 -4
- package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +3 -3
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/editor-step-hook.py +11 -6
- package/package.json +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor-BBAGP_mE.js +0 -10
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-BLQMSKZa.js +0 -41
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-CF164ouH.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/globals-COUSHTyZ.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-9c70d1f3.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-CrAK28Bc.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BtbLQkKd.js +0 -433
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTimestamp": "2026-03-
|
|
3
|
-
"buildTime":
|
|
4
|
-
"gitCommit": "
|
|
2
|
+
"buildTimestamp": "2026-03-12T17:48:53.671Z",
|
|
3
|
+
"buildTime": 1773337733671,
|
|
4
|
+
"gitCommit": "e05777544c54b403dfcde166b28b6ec249aec06a",
|
|
5
5
|
"nodeVersion": "v20.20.0",
|
|
6
6
|
"contentHash": "c6e453b5eb8471fdcb3e34085216f7d6523809504f12ddb1c6ee11665149d827",
|
|
7
|
-
"buildNumber":
|
|
8
|
-
"semanticVersion": "0.1.
|
|
9
|
-
"version": "0.1.
|
|
7
|
+
"buildNumber": 962,
|
|
8
|
+
"semanticVersion": "0.1.962",
|
|
9
|
+
"version": "0.1.962 (2026-03-12T17:48+c6e453b)"
|
|
10
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
[3/
|
|
3
|
-
[3/
|
|
2
|
+
[3/12/2026, 5:48:53 PM] > codeyam-combo@1.0.0 mergeDependencies
|
|
3
|
+
[3/12/2026, 5:48:53 PM] > node ./scripts/mergePackageJsonFiles.cjs
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
[3/
|
|
6
|
+
[3/12/2026, 5:48:53 PM] Merged dependencies into root package.json
|
|
7
7
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Structural test: the CLI dispatch switch in editor.ts must have case labels
|
|
5
|
+
* for every step 1–16. Without this test, it's easy to add new steps
|
|
6
|
+
* (e.g. 14, 15, 16) to the printStep functions and STEP_LABELS but forget
|
|
7
|
+
* to add matching case labels to the switch statement — causing `codeyam editor N`
|
|
8
|
+
* to silently do nothing for the missing steps.
|
|
9
|
+
*
|
|
10
|
+
* This test reads the source file and parses the switch block that dispatches
|
|
11
|
+
* step numbers to their handlers.
|
|
12
|
+
*/
|
|
13
|
+
describe('editor CLI step dispatch', () => {
|
|
14
|
+
const editorSource = fs.readFileSync(path.join(__dirname, '..', 'editor.ts'), 'utf8');
|
|
15
|
+
it('should have switch case labels for all steps 1–16', () => {
|
|
16
|
+
// Find the switch(step) block in the CLI dispatch section.
|
|
17
|
+
// There are two stepFns definitions in editor.ts:
|
|
18
|
+
// 1. Test/debug scenario generator (~line 4658) — uses a for-loop, not a switch
|
|
19
|
+
// 2. CLI dispatch (~line 5263) — uses switch(step) { case N: ... }
|
|
20
|
+
//
|
|
21
|
+
// We need to verify the second one (CLI dispatch) has cases for all 16 steps.
|
|
22
|
+
// Find all `case N:` labels in the file. The CLI dispatch switch is the
|
|
23
|
+
// only switch on `step` that uses numbered cases.
|
|
24
|
+
const switchMatch = editorSource.match(/switch\s*\(step\)\s*\{([\s\S]*?)\n\s{4}\}/);
|
|
25
|
+
expect(switchMatch).not.toBeNull();
|
|
26
|
+
const switchBody = switchMatch[1];
|
|
27
|
+
for (let step = 1; step <= 16; step++) {
|
|
28
|
+
const casePattern = new RegExp(`case\\s+${step}\\s*[:{]`);
|
|
29
|
+
expect(switchBody).toMatch(casePattern);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
it('should have STEP_LABELS entries for all steps 1–16', () => {
|
|
33
|
+
for (let step = 1; step <= 16; step++) {
|
|
34
|
+
const labelPattern = new RegExp(`${step}:\\s*'[^']+'`);
|
|
35
|
+
expect(editorSource).toMatch(labelPattern);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
it('should have printStep functions defined for all steps 1–16', () => {
|
|
39
|
+
for (let step = 1; step <= 16; step++) {
|
|
40
|
+
const fnPattern = new RegExp(`function\\s+printStep${step}\\s*\\(`);
|
|
41
|
+
expect(editorSource).toMatch(fnPattern);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=editor.stepDispatch.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.stepDispatch.test.js","sourceRoot":"","sources":["../../../../../src/commands/__tests__/editor.stepDispatch.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;;GASG;AACH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,EACvC,MAAM,CACP,CAAC;IAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,2DAA2D;QAC3D,kDAAkD;QAClD,kFAAkF;QAClF,qEAAqE;QACrE,EAAE;QACF,8EAA8E;QAE9E,wEAAwE;QACxE,kDAAkD;QAClD,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CACpC,2CAA2C,CAC5C,CAAC;QACF,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAEnC,MAAM,UAAU,GAAG,WAAY,CAAC,CAAC,CAAC,CAAC;QAEnC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;YACtC,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,WAAW,IAAI,UAAU,CAAC,CAAC;YAC1D,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;YACtC,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC;YACvD,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;YACtC,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,wBAAwB,IAAI,SAAS,CAAC,CAAC;YACpE,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -11,7 +11,7 @@ import { IS_INTERNAL_BUILD } from "../utils/buildFlags.js";
|
|
|
11
11
|
import { startBackgroundServer } from "../utils/backgroundServer.js";
|
|
12
12
|
import { installClaudeCodeSkills } from "../utils/install-skills.js";
|
|
13
13
|
import { setupClaudeCodeSettings } from "../utils/setupClaudeCodeSettings.js";
|
|
14
|
-
import {
|
|
14
|
+
import { ensureAnalyzerFinalized } from "../utils/analyzerFinalization.js";
|
|
15
15
|
import { APP_FORMATS, TECH_STACKS } from "../data/techStacks.js";
|
|
16
16
|
import { getProjectRoot as getStateProjectRoot } from "../state.js";
|
|
17
17
|
import initCommand from "./init.js";
|
|
@@ -36,6 +36,9 @@ const STEP_LABELS = {
|
|
|
36
36
|
11: 'Journal',
|
|
37
37
|
12: 'Review',
|
|
38
38
|
13: 'Present',
|
|
39
|
+
14: 'Commit',
|
|
40
|
+
15: 'Finalize',
|
|
41
|
+
16: 'Push',
|
|
39
42
|
};
|
|
40
43
|
/**
|
|
41
44
|
* Append a JSONL log entry to .codeyam/logs/editor-log.jsonl
|
|
@@ -161,13 +164,13 @@ function stepHeader(step, title, feature) {
|
|
|
161
164
|
console.log();
|
|
162
165
|
}
|
|
163
166
|
/**
|
|
164
|
-
* Print a colored progress tracker showing all
|
|
167
|
+
* Print a colored progress tracker showing all 16 steps.
|
|
165
168
|
* Steps before `current` are green ✓, `current` is bold cyan →, future steps are dim ○.
|
|
166
169
|
*/
|
|
167
170
|
function printProgressTracker(current) {
|
|
168
171
|
console.log();
|
|
169
172
|
console.log(chalk.dim(' ┌─────────────────────────────────────┐'));
|
|
170
|
-
for (let i = 1; i <=
|
|
173
|
+
for (let i = 1; i <= 16; i++) {
|
|
171
174
|
const label = STEP_LABELS[i];
|
|
172
175
|
const num = i < 10 ? ` ${i}` : `${i}`;
|
|
173
176
|
const content = `${num}. ${label.padEnd(28)}`;
|
|
@@ -205,7 +208,7 @@ function stopGate(current, opts) {
|
|
|
205
208
|
console.log(chalk.yellow('For the CURRENT step (→), show each checklist item with ✓ (done) or ✗ (skipped + reason).'));
|
|
206
209
|
console.log(chalk.yellow('If any items are ✗, explain why and ask if the user wants to address them.'));
|
|
207
210
|
console.log();
|
|
208
|
-
if (current <
|
|
211
|
+
if (current < 16) {
|
|
209
212
|
console.log(chalk.green('When done, run: ') +
|
|
210
213
|
chalk.bold(`codeyam editor ${current + 1}`));
|
|
211
214
|
}
|
|
@@ -249,6 +252,14 @@ function printResumptionHeader(step) {
|
|
|
249
252
|
],
|
|
250
253
|
12: ['Re-verify is safe to repeat — just re-run the checks'],
|
|
251
254
|
13: ['Check if commit already made:\n `git log --oneline -3`'],
|
|
255
|
+
14: ['Check if commit already made:\n `git log --oneline -3`'],
|
|
256
|
+
15: [
|
|
257
|
+
'Check if journal was already updated with commit SHA:\n `codeyam editor journal-list`',
|
|
258
|
+
'Check if commit was already amended:\n `git log --oneline -3`',
|
|
259
|
+
],
|
|
260
|
+
16: [
|
|
261
|
+
'Check if already pushed:\n `git remote -v && git log --oneline origin/HEAD..HEAD 2>/dev/null`',
|
|
262
|
+
],
|
|
252
263
|
};
|
|
253
264
|
const label = STEP_LABELS[step] || 'Unknown';
|
|
254
265
|
console.log(chalk.bold.yellow(`━━━ RESUMING Step ${step}: ${label} ━━━`));
|
|
@@ -353,7 +364,7 @@ function parseDebugTargets(target) {
|
|
|
353
364
|
}
|
|
354
365
|
if (entry.startsWith('step-')) {
|
|
355
366
|
const num = parseInt(entry.replace('step-', ''), 10);
|
|
356
|
-
if (!isNaN(num) && num >= 1 && num <=
|
|
367
|
+
if (!isNaN(num) && num >= 1 && num <= 16) {
|
|
357
368
|
valid.add(`step-${num}`);
|
|
358
369
|
continue;
|
|
359
370
|
}
|
|
@@ -541,7 +552,7 @@ function printCycleOverview(root, state) {
|
|
|
541
552
|
console.log(chalk.yellow('This applies even after committing — always use the change workflow.'));
|
|
542
553
|
}
|
|
543
554
|
else {
|
|
544
|
-
console.log('Each feature follows
|
|
555
|
+
console.log('Each feature follows 16 steps. You MUST run each command in order:');
|
|
545
556
|
console.log();
|
|
546
557
|
console.log(` ${chalk.bold.yellow(' 1')} ${chalk.bold('Plan')} — Plan the feature, confirm with user`);
|
|
547
558
|
console.log(` ${chalk.bold.yellow(' 2')} ${chalk.bold('Prototype')} — Build a working prototype fast`);
|
|
@@ -556,6 +567,9 @@ function printCycleOverview(root, state) {
|
|
|
556
567
|
console.log(` ${chalk.bold.yellow('11')} ${chalk.bold('Journal')} — Create/update journal entry`);
|
|
557
568
|
console.log(` ${chalk.bold.yellow('12')} ${chalk.bold('Review')} — Verify screenshots and audit`);
|
|
558
569
|
console.log(` ${chalk.bold.yellow('13')} ${chalk.bold('Present')} — Present summary, get approval`);
|
|
570
|
+
console.log(` ${chalk.bold.yellow('14')} ${chalk.bold('Commit')} — Commit all changes`);
|
|
571
|
+
console.log(` ${chalk.bold.yellow('15')} ${chalk.bold('Finalize')} — Journal update + amend commit`);
|
|
572
|
+
console.log(` ${chalk.bold.yellow('16')} ${chalk.bold('Push')} — Push to remote`);
|
|
559
573
|
console.log();
|
|
560
574
|
console.log(chalk.green('Start now: ') + chalk.bold('codeyam editor 1'));
|
|
561
575
|
console.log(chalk.dim(' If the user already described what they want, pass it: codeyam editor 1 --prompt "their message"'));
|
|
@@ -570,19 +584,19 @@ function printStep1(root, feature, options, userPrompt) {
|
|
|
570
584
|
if (!isResuming) {
|
|
571
585
|
clearState(root);
|
|
572
586
|
}
|
|
573
|
-
//
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
587
|
+
// Always persist state so step 2's validation sees that step 1 ran.
|
|
588
|
+
// The feature name may not be known yet (it's an output of planning) —
|
|
589
|
+
// use an empty string as placeholder; step 2 requires --feature anyway.
|
|
590
|
+
const now = new Date().toISOString();
|
|
591
|
+
writeState(root, {
|
|
592
|
+
feature: feature || prevState?.feature || '',
|
|
593
|
+
step: 1,
|
|
594
|
+
label: STEP_LABELS[1],
|
|
595
|
+
startedAt: isResuming ? prevState.startedAt : now,
|
|
596
|
+
featureStartedAt: isResuming ? prevState.featureStartedAt : now,
|
|
597
|
+
appFormats: options?.appFormats || prevState?.appFormats,
|
|
598
|
+
techStackId: options?.techStackId || prevState?.techStackId,
|
|
599
|
+
});
|
|
586
600
|
// Save the user's original prompt to a separate file
|
|
587
601
|
if (userPrompt) {
|
|
588
602
|
const promptPath = path.join(root, '.codeyam', 'editor-user-prompt.txt');
|
|
@@ -818,7 +832,7 @@ function printStep3(root, feature) {
|
|
|
818
832
|
console.log(chalk.bold('Present a selection menu to the user (use AskUserQuestion with these EXACT option labels):'));
|
|
819
833
|
console.log(chalk.green(' Option 1 label: "The live preview is displaying what I expected"') + chalk.dim(' — proceed to step 4'));
|
|
820
834
|
console.log(chalk.yellow(' Option 2 label: "I\'d like some changes"') +
|
|
821
|
-
chalk.dim(' —
|
|
835
|
+
chalk.dim(' — make changes, refresh preview, re-run `codeyam editor 3`'));
|
|
822
836
|
console.log();
|
|
823
837
|
console.log(chalk.dim('Wait for user approval before moving on. Refactoring and scenarios happen in later steps.'));
|
|
824
838
|
stopGate(3, { confirm: true });
|
|
@@ -1325,32 +1339,98 @@ function printStep13(root, feature) {
|
|
|
1325
1339
|
chalk.dim(' — describe changes, then re-verify'));
|
|
1326
1340
|
console.log();
|
|
1327
1341
|
console.log(chalk.bold('If the user chooses "Save & commit":'));
|
|
1328
|
-
checkbox(
|
|
1342
|
+
checkbox('Advance to the commit step: `codeyam editor 14`');
|
|
1343
|
+
console.log();
|
|
1344
|
+
console.log(chalk.bold('If the user chooses "Make changes" (or asks for ANY change, even as a question):'));
|
|
1345
|
+
checkbox(`Hide the results panel: \`codeyam editor hide-results\``);
|
|
1346
|
+
checkbox('Ask what changes the user wants (if not already clear)');
|
|
1347
|
+
checkbox(`Run: \`codeyam editor change "${feature}"\` — this gives you the change checklist`);
|
|
1348
|
+
checkbox('THEN make the requested changes and follow the checklist');
|
|
1349
|
+
console.log(chalk.red.bold(' IMPORTANT: Always run the change command BEFORE writing any code.'));
|
|
1350
|
+
stopGate(13, { confirm: true });
|
|
1351
|
+
}
|
|
1352
|
+
// ─── Step 14: Commit ─────────────────────────────────────────────────
|
|
1353
|
+
function printStep14(root, feature) {
|
|
1354
|
+
const prevState = readState(root);
|
|
1355
|
+
const isResuming = prevState?.step === 14;
|
|
1356
|
+
const now = new Date().toISOString();
|
|
1357
|
+
writeState(root, {
|
|
1358
|
+
feature,
|
|
1359
|
+
step: 14,
|
|
1360
|
+
label: STEP_LABELS[14],
|
|
1361
|
+
startedAt: isResuming ? prevState.startedAt : now,
|
|
1362
|
+
featureStartedAt: prevState?.featureStartedAt || now,
|
|
1363
|
+
});
|
|
1364
|
+
logEvent(root, 'step', { step: 14, label: 'Commit', feature });
|
|
1365
|
+
stepHeader(14, 'Commit', feature);
|
|
1366
|
+
if (isResuming) {
|
|
1367
|
+
printResumptionHeader(14);
|
|
1368
|
+
}
|
|
1369
|
+
console.log('Commit all changes for this feature.');
|
|
1370
|
+
console.log();
|
|
1371
|
+
console.log(chalk.bold('Checklist:'));
|
|
1372
|
+
checkbox(`Hide the results panel: \`codeyam editor hide-results\``);
|
|
1329
1373
|
checkbox(`Git commit using the journal description: \`codeyam editor commit '{"message":"feat: <title>\\n\\n<journal description>"}'\``);
|
|
1330
1374
|
console.log(chalk.dim(' The commit message body MUST match the journal description exactly'));
|
|
1375
|
+
stopGate(14);
|
|
1376
|
+
}
|
|
1377
|
+
// ─── Step 15: Finalize ───────────────────────────────────────────────
|
|
1378
|
+
function printStep15(root, feature) {
|
|
1379
|
+
const prevState = readState(root);
|
|
1380
|
+
const isResuming = prevState?.step === 15;
|
|
1381
|
+
const now = new Date().toISOString();
|
|
1382
|
+
writeState(root, {
|
|
1383
|
+
feature,
|
|
1384
|
+
step: 15,
|
|
1385
|
+
label: STEP_LABELS[15],
|
|
1386
|
+
startedAt: isResuming ? prevState.startedAt : now,
|
|
1387
|
+
featureStartedAt: prevState?.featureStartedAt || now,
|
|
1388
|
+
});
|
|
1389
|
+
logEvent(root, 'step', { step: 15, label: 'Finalize', feature });
|
|
1390
|
+
stepHeader(15, 'Finalize', feature);
|
|
1391
|
+
if (isResuming) {
|
|
1392
|
+
printResumptionHeader(15);
|
|
1393
|
+
}
|
|
1394
|
+
console.log('Update the journal with the commit SHA and amend the commit.');
|
|
1395
|
+
console.log();
|
|
1396
|
+
console.log(chalk.bold('Checklist:'));
|
|
1331
1397
|
checkbox(`Update journal with commit SHA: \`codeyam editor journal-update '{"time":"<journal entry time>","commitSha":"<sha>","commitMessage":"feat: <title>"}'\``);
|
|
1332
1398
|
checkbox('Amend the commit to include the journal update: `git add .codeyam/journal/ && git commit --amend --no-edit`');
|
|
1333
1399
|
console.log(chalk.dim(' The journal-update modifies journal files after the commit — amend to keep the tree clean.'));
|
|
1400
|
+
stopGate(15);
|
|
1401
|
+
}
|
|
1402
|
+
// ─── Step 16: Push ───────────────────────────────────────────────────
|
|
1403
|
+
function printStep16(root, feature) {
|
|
1404
|
+
const prevState = readState(root);
|
|
1405
|
+
const isResuming = prevState?.step === 16;
|
|
1406
|
+
const now = new Date().toISOString();
|
|
1407
|
+
writeState(root, {
|
|
1408
|
+
feature,
|
|
1409
|
+
step: 16,
|
|
1410
|
+
label: STEP_LABELS[16],
|
|
1411
|
+
startedAt: isResuming ? prevState.startedAt : now,
|
|
1412
|
+
featureStartedAt: prevState?.featureStartedAt || now,
|
|
1413
|
+
});
|
|
1414
|
+
logEvent(root, 'step', { step: 16, label: 'Push', feature });
|
|
1415
|
+
stepHeader(16, 'Push', feature);
|
|
1416
|
+
if (isResuming) {
|
|
1417
|
+
printResumptionHeader(16);
|
|
1418
|
+
}
|
|
1419
|
+
console.log('Push the commit to the remote repository.');
|
|
1420
|
+
console.log();
|
|
1421
|
+
console.log(chalk.bold('Checklist:'));
|
|
1334
1422
|
checkbox('Check if a git remote is configured: `git remote -v`');
|
|
1335
|
-
|
|
1423
|
+
checkbox("Offer to push to remote (AskUserQuestion — STOP and wait for the user's answer before proceeding):");
|
|
1424
|
+
console.log(chalk.dim(' If a remote exists, ask (AskUserQuestion): "Would you like me to push this commit to the remote?" with options "Yes, push" and "No, skip"'));
|
|
1336
1425
|
console.log(chalk.dim(' If the user says yes, run: `git push`'));
|
|
1337
|
-
console.log(chalk.dim(' If NO remote exists, ask: "This project doesn\'t have a git remote yet. Would you like help setting one up? I can walk you through creating a GitHub repository."'));
|
|
1426
|
+
console.log(chalk.dim(' If NO remote exists, ask (AskUserQuestion): "This project doesn\'t have a git remote yet. Would you like help setting one up? I can walk you through creating a GitHub repository." with options "Yes, set up remote" and "No, skip"'));
|
|
1338
1427
|
console.log(chalk.dim(' If the user wants help, guide them through `gh repo create` or manual GitHub setup, then push.'));
|
|
1339
|
-
|
|
1340
|
-
chalk.bold('codeyam editor steps') +
|
|
1341
|
-
chalk.green(' to start the next feature'));
|
|
1428
|
+
checkbox('After the user responds, run: `codeyam editor steps` to start the next feature');
|
|
1342
1429
|
console.log();
|
|
1343
1430
|
console.log(chalk.red.bold(' If the user reports a bug or requests a fix after committing:'));
|
|
1344
1431
|
console.log(chalk.red.bold(' You MUST still run `codeyam editor change` before making any changes.'));
|
|
1345
1432
|
console.log(chalk.red.bold(' The change workflow applies to ALL changes — post-commit fixes are not an exception.'));
|
|
1346
|
-
|
|
1347
|
-
console.log(chalk.bold('If the user chooses "Make changes" (or asks for ANY change, even as a question):'));
|
|
1348
|
-
checkbox(`Hide the results panel: \`codeyam editor hide-results\``);
|
|
1349
|
-
checkbox('Ask what changes the user wants (if not already clear)');
|
|
1350
|
-
checkbox(`Run: \`codeyam editor change "${feature}"\` — this gives you the change checklist`);
|
|
1351
|
-
checkbox('THEN make the requested changes and follow the checklist');
|
|
1352
|
-
console.log(chalk.red.bold(' IMPORTANT: Always run the change command BEFORE writing any code.'));
|
|
1353
|
-
stopGate(13, { confirm: true });
|
|
1433
|
+
stopGate(16, { confirm: true });
|
|
1354
1434
|
}
|
|
1355
1435
|
// ─── Command definition ───────────────────────────────────────────────
|
|
1356
1436
|
// ─── Analyze-imports subcommand ────────────────────────────────────────
|
|
@@ -1876,15 +1956,15 @@ async function handleDependents(entityName) {
|
|
|
1876
1956
|
* `codeyam editor change <feature>`
|
|
1877
1957
|
*
|
|
1878
1958
|
* Prints a condensed post-change checklist that guides Claude through
|
|
1879
|
-
* re-verifying after user-requested modifications.
|
|
1880
|
-
*
|
|
1881
|
-
*
|
|
1959
|
+
* re-verifying after user-requested modifications. When called from
|
|
1960
|
+
* step 13+, this loops back to step 13 (present). When called from an
|
|
1961
|
+
* earlier step, it returns to that step so the normal flow continues.
|
|
1882
1962
|
*/
|
|
1883
1963
|
function handleChange(feature) {
|
|
1884
1964
|
const root = getProjectRoot();
|
|
1965
|
+
const state = readState(root);
|
|
1885
1966
|
if (!feature) {
|
|
1886
1967
|
// Try to read feature from state
|
|
1887
|
-
const state = readState(root);
|
|
1888
1968
|
if (state?.feature) {
|
|
1889
1969
|
feature = state.feature;
|
|
1890
1970
|
}
|
|
@@ -1894,6 +1974,7 @@ function handleChange(feature) {
|
|
|
1894
1974
|
process.exit(1);
|
|
1895
1975
|
}
|
|
1896
1976
|
}
|
|
1977
|
+
const currentStep = state?.step ?? 13;
|
|
1897
1978
|
const port = getServerPort();
|
|
1898
1979
|
console.log();
|
|
1899
1980
|
console.log(chalk.bold.cyan('━━━ Change Loop ━━━'));
|
|
@@ -1961,12 +2042,24 @@ function handleChange(feature) {
|
|
|
1961
2042
|
console.log(chalk.dim(' Always update the existing uncommitted entry — do NOT create a new one.'));
|
|
1962
2043
|
console.log(chalk.dim(' Only create a new entry (POST) if no uncommitted entry exists for this feature.'));
|
|
1963
2044
|
console.log();
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2045
|
+
// If the change was initiated from a step before 13, return to that step
|
|
2046
|
+
// instead of jumping to step 13. The change workflow should only loop to
|
|
2047
|
+
// step 13 when changes are requested FROM step 13.
|
|
2048
|
+
if (currentStep < 13) {
|
|
2049
|
+
console.log(chalk.red(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2050
|
+
console.log(chalk.red.bold(' REQUIRED: Return to current step'));
|
|
2051
|
+
console.log(chalk.red.bold(' When all checks pass, you MUST run: ') +
|
|
2052
|
+
chalk.bold(`codeyam editor ${currentStep}`));
|
|
2053
|
+
console.log(chalk.red(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2054
|
+
}
|
|
2055
|
+
else {
|
|
2056
|
+
console.log(chalk.red(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2057
|
+
console.log(chalk.red.bold(' REQUIRED: Show Results'));
|
|
2058
|
+
console.log(chalk.red.bold(' When all checks pass, you MUST run: ') +
|
|
2059
|
+
chalk.bold(`codeyam editor 13`));
|
|
2060
|
+
console.log(chalk.red.bold(' The user ALWAYS expects to see results after changes. DO NOT skip this step.'));
|
|
2061
|
+
console.log(chalk.red(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
2062
|
+
}
|
|
1970
2063
|
console.log();
|
|
1971
2064
|
}
|
|
1972
2065
|
// ─── Audit gate ─────────────────────────────────────────────────────
|
|
@@ -2359,6 +2452,9 @@ async function handleTemplate() {
|
|
|
2359
2452
|
// Config parse error is non-fatal
|
|
2360
2453
|
}
|
|
2361
2454
|
}
|
|
2455
|
+
// 5b. Write a fresh prototypeId so the proxy clears stale localStorage
|
|
2456
|
+
const activeScenarioPath = path.join(root, '.codeyam', 'active-scenario.json');
|
|
2457
|
+
fs.writeFileSync(activeScenarioPath, JSON.stringify({ prototypeId: Date.now().toString() }), 'utf-8');
|
|
2362
2458
|
// 6. Trigger editor-refresh so the server picks up the new project
|
|
2363
2459
|
console.log(chalk.bold('Refreshing editor...'));
|
|
2364
2460
|
try {
|
|
@@ -2570,8 +2666,11 @@ function handleEditorDebug(args) {
|
|
|
2570
2666
|
11: printStep11,
|
|
2571
2667
|
12: printStep12,
|
|
2572
2668
|
13: printStep13,
|
|
2669
|
+
14: printStep14,
|
|
2670
|
+
15: printStep15,
|
|
2671
|
+
16: printStep16,
|
|
2573
2672
|
};
|
|
2574
|
-
for (let step = 1; step <=
|
|
2673
|
+
for (let step = 1; step <= 16; step++) {
|
|
2575
2674
|
const stepId = `step-${step}`;
|
|
2576
2675
|
if (!wants(stepId))
|
|
2577
2676
|
continue;
|
|
@@ -2650,8 +2749,8 @@ const editorCommand = {
|
|
|
2650
2749
|
describe: 'Editor mode guided workflow',
|
|
2651
2750
|
builder: (yargs) => {
|
|
2652
2751
|
const stepDescription = IS_INTERNAL_BUILD
|
|
2653
|
-
? 'Step number (1-
|
|
2654
|
-
: 'Step number (1-
|
|
2752
|
+
? 'Step number (1-16) or subcommand (template, register, isolate, analyze-imports, dependents, audit, scenarios, scenario-coverage, change, sync, debug, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors)'
|
|
2753
|
+
: 'Step number (1-16) or subcommand (template, register, isolate, analyze-imports, dependents, audit, scenarios, scenario-coverage, change, sync, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors)';
|
|
2655
2754
|
let builder = yargs
|
|
2656
2755
|
.positional('step', {
|
|
2657
2756
|
type: 'string',
|
|
@@ -2687,7 +2786,7 @@ const editorCommand = {
|
|
|
2687
2786
|
builder = builder
|
|
2688
2787
|
.option('target', {
|
|
2689
2788
|
type: 'string',
|
|
2690
|
-
describe: 'Debug target (setup, overview, overview-with-state, step-1..step-
|
|
2789
|
+
describe: 'Debug target (setup, overview, overview-with-state, step-1..step-16, or comma-separated list)',
|
|
2691
2790
|
})
|
|
2692
2791
|
.option('resume', {
|
|
2693
2792
|
type: 'boolean',
|
|
@@ -2819,9 +2918,9 @@ const editorCommand = {
|
|
|
2819
2918
|
}
|
|
2820
2919
|
else {
|
|
2821
2920
|
const state = readState(root);
|
|
2822
|
-
// Clear prompt file when feature is done (step
|
|
2921
|
+
// Clear prompt file when feature is done (step 16) so the hook
|
|
2823
2922
|
// can capture the next feature request from the user.
|
|
2824
|
-
if (state?.step ===
|
|
2923
|
+
if (state?.step === 16) {
|
|
2825
2924
|
clearEditorUserPrompt(root);
|
|
2826
2925
|
}
|
|
2827
2926
|
printCycleOverview(root, state);
|
|
@@ -2829,8 +2928,8 @@ const editorCommand = {
|
|
|
2829
2928
|
return;
|
|
2830
2929
|
}
|
|
2831
2930
|
const step = argv.step ? parseInt(argv.step, 10) : undefined;
|
|
2832
|
-
if (step != null && (isNaN(step) || step < 1 || step >
|
|
2833
|
-
console.error(chalk.red(`Error: Invalid step "${argv.step}". Must be 1-
|
|
2931
|
+
if (step != null && (isNaN(step) || step < 1 || step > 16)) {
|
|
2932
|
+
console.error(chalk.red(`Error: Invalid step "${argv.step}". Must be 1-16.`));
|
|
2834
2933
|
process.exit(1);
|
|
2835
2934
|
}
|
|
2836
2935
|
if (step == null) {
|
|
@@ -2970,29 +3069,15 @@ const editorCommand = {
|
|
|
2970
3069
|
editorMode,
|
|
2971
3070
|
});
|
|
2972
3071
|
// Auto-finalize analyzer so codeyam analyze works
|
|
2973
|
-
if (editorMode
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
if (fs.existsSync(templatePath)) {
|
|
2978
|
-
console.log(' Setting up simulations (first time only)...');
|
|
2979
|
-
execSync('npm install --include=dev', {
|
|
2980
|
-
cwd: templatePath,
|
|
2981
|
-
stdio: 'pipe',
|
|
2982
|
-
});
|
|
2983
|
-
execSync('npx playwright install chromium', {
|
|
2984
|
-
cwd: templatePath,
|
|
2985
|
-
stdio: 'pipe',
|
|
2986
|
-
});
|
|
2987
|
-
execSync('npm run build', {
|
|
2988
|
-
cwd: templatePath,
|
|
2989
|
-
stdio: 'pipe',
|
|
2990
|
-
});
|
|
2991
|
-
fs.writeFileSync(path.join(templatePath, '.finalized'), new Date().toISOString());
|
|
2992
|
-
}
|
|
3072
|
+
if (editorMode) {
|
|
3073
|
+
const finalization = ensureAnalyzerFinalized();
|
|
3074
|
+
if (finalization.needed) {
|
|
3075
|
+
console.log(` Setting up simulations (${finalization.stepsRun.join(', ')})...`);
|
|
2993
3076
|
}
|
|
2994
|
-
|
|
2995
|
-
|
|
3077
|
+
if (finalization.errors.length > 0) {
|
|
3078
|
+
for (const err of finalization.errors) {
|
|
3079
|
+
console.warn(` Warning: ${err.step} failed: ${err.message}`);
|
|
3080
|
+
}
|
|
2996
3081
|
}
|
|
2997
3082
|
}
|
|
2998
3083
|
// Start background server (handles killing existing servers internally)
|
|
@@ -3043,11 +3128,17 @@ const editorCommand = {
|
|
|
3043
3128
|
return;
|
|
3044
3129
|
}
|
|
3045
3130
|
const state = readState(root);
|
|
3046
|
-
// Validate step transition — prevent skipping steps
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3131
|
+
// Validate step transition — prevent skipping steps.
|
|
3132
|
+
// Exception: step 2 with --feature is always allowed because step 1's
|
|
3133
|
+
// instructions explicitly tell Claude to run `codeyam editor 2 --feature "..."`.
|
|
3134
|
+
// Step 1 is planning-only and may not persist state (no --feature flag).
|
|
3135
|
+
const skipValidation = step === 2 && argv.feature;
|
|
3136
|
+
if (!skipValidation) {
|
|
3137
|
+
const stepError = validateStepTransition(step, state?.step ?? null);
|
|
3138
|
+
if (stepError) {
|
|
3139
|
+
console.error(chalk.red(`Error: ${stepError}`));
|
|
3140
|
+
process.exit(1);
|
|
3141
|
+
}
|
|
3051
3142
|
}
|
|
3052
3143
|
switch (step) {
|
|
3053
3144
|
case 1: {
|
|
@@ -3080,7 +3171,10 @@ const editorCommand = {
|
|
|
3080
3171
|
case 10:
|
|
3081
3172
|
case 11:
|
|
3082
3173
|
case 12:
|
|
3083
|
-
case 13:
|
|
3174
|
+
case 13:
|
|
3175
|
+
case 14:
|
|
3176
|
+
case 15:
|
|
3177
|
+
case 16: {
|
|
3084
3178
|
const feature = argv.feature || state?.feature;
|
|
3085
3179
|
if (!feature) {
|
|
3086
3180
|
console.error(chalk.red('Error: No feature in progress. Run codeyam editor 1 first.'));
|
|
@@ -3107,6 +3201,9 @@ const editorCommand = {
|
|
|
3107
3201
|
11: printStep11,
|
|
3108
3202
|
12: printStep12,
|
|
3109
3203
|
13: printStep13,
|
|
3204
|
+
14: printStep14,
|
|
3205
|
+
15: printStep15,
|
|
3206
|
+
16: printStep16,
|
|
3110
3207
|
};
|
|
3111
3208
|
stepFns[step](root, feature);
|
|
3112
3209
|
break;
|