rafcode 3.0.0 → 3.8.0
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/.claude/settings.local.json +3 -1
- package/CLAUDE.md +0 -1
- package/RAF/38-dual-wielder/decisions.md +9 -0
- package/RAF/38-dual-wielder/input.md +6 -1
- package/RAF/38-dual-wielder/outcomes/8-e2e-test-codex-provider.md +139 -0
- package/RAF/38-dual-wielder/plans/8-e2e-test-codex-provider.md +95 -0
- package/RAF/39-pathless-rover/decisions.md +16 -0
- package/RAF/39-pathless-rover/input.md +2 -0
- package/RAF/39-pathless-rover/outcomes/1-fix-codex-stream-renderer.md +21 -0
- package/RAF/39-pathless-rover/outcomes/2-wire-provider-flag.md +28 -0
- package/RAF/39-pathless-rover/outcomes/3-remove-worktree-flag-do.md +41 -0
- package/RAF/39-pathless-rover/outcomes/4-remove-worktree-flag-plan-amend.md +30 -0
- package/RAF/39-pathless-rover/outcomes/5-update-prompts-and-docs.md +26 -0
- package/RAF/39-pathless-rover/plans/1-fix-codex-stream-renderer.md +43 -0
- package/RAF/39-pathless-rover/plans/2-wire-provider-flag.md +48 -0
- package/RAF/39-pathless-rover/plans/3-remove-worktree-flag-do.md +41 -0
- package/RAF/39-pathless-rover/plans/4-remove-worktree-flag-plan-amend.md +43 -0
- package/RAF/39-pathless-rover/plans/5-update-prompts-and-docs.md +31 -0
- package/RAF/40-numeric-order-fix/decisions.md +7 -0
- package/RAF/40-numeric-order-fix/input.md +19 -0
- package/RAF/40-numeric-order-fix/outcomes/1-fix-numeric-sort-order.md +18 -0
- package/RAF/40-numeric-order-fix/outcomes/2-add-npm-keywords.md +10 -0
- package/RAF/40-numeric-order-fix/plans/1-fix-numeric-sort-order.md +48 -0
- package/RAF/40-numeric-order-fix/plans/2-add-npm-keywords.md +23 -0
- package/RAF/41-echo-chamber/decisions.md +13 -0
- package/RAF/41-echo-chamber/input.md +4 -0
- package/RAF/41-echo-chamber/outcomes/1-update-codex-model-defaults.md +24 -0
- package/RAF/41-echo-chamber/outcomes/2-e2e-test-codex-provider.md +74 -0
- package/RAF/41-echo-chamber/plans/1-update-codex-model-defaults.md +28 -0
- package/RAF/41-echo-chamber/plans/2-e2e-test-codex-provider.md +103 -0
- package/RAF/42-patch-parade/decisions.md +29 -0
- package/RAF/42-patch-parade/input.md +9 -0
- package/RAF/42-patch-parade/outcomes/1-fix-codex-model-resolution.md +36 -0
- package/RAF/42-patch-parade/outcomes/2-fix-provider-aware-name-generation.md +31 -0
- package/RAF/42-patch-parade/outcomes/3-fix-codex-error-event-rendering.md +32 -0
- package/RAF/42-patch-parade/outcomes/4-update-cli-help-docs.md +28 -0
- package/RAF/42-patch-parade/outcomes/5-update-default-codex-models-to-gpt-5-4.md +33 -0
- package/RAF/42-patch-parade/outcomes/6-unify-model-config-schema.md +89 -0
- package/RAF/42-patch-parade/plans/1-fix-codex-model-resolution.md +35 -0
- package/RAF/42-patch-parade/plans/2-fix-provider-aware-name-generation.md +38 -0
- package/RAF/42-patch-parade/plans/3-fix-codex-error-event-rendering.md +32 -0
- package/RAF/42-patch-parade/plans/4-update-cli-help-docs.md +31 -0
- package/RAF/42-patch-parade/plans/5-update-default-codex-models-to-gpt-5-4.md +35 -0
- package/RAF/42-patch-parade/plans/6-unify-model-config-schema.md +46 -0
- package/RAF/43-swiss-army/decisions.md +34 -0
- package/RAF/43-swiss-army/input.md +7 -0
- package/RAF/43-swiss-army/outcomes/1-fix-model-validation.md +21 -0
- package/RAF/43-swiss-army/outcomes/2-update-commit-format.md +31 -0
- package/RAF/43-swiss-army/outcomes/3-wire-reasoning-effort.md +28 -0
- package/RAF/43-swiss-army/outcomes/4-remove-provider-flag.md +27 -0
- package/RAF/43-swiss-army/outcomes/5-config-wizard-validation.md +23 -0
- package/RAF/43-swiss-army/outcomes/6-add-fast-mode.md +32 -0
- package/RAF/43-swiss-army/outcomes/7-config-preset.md +31 -0
- package/RAF/43-swiss-army/plans/1-fix-model-validation.md +38 -0
- package/RAF/43-swiss-army/plans/2-update-commit-format.md +46 -0
- package/RAF/43-swiss-army/plans/3-wire-reasoning-effort.md +39 -0
- package/RAF/43-swiss-army/plans/4-remove-provider-flag.md +43 -0
- package/RAF/43-swiss-army/plans/5-config-wizard-validation.md +42 -0
- package/RAF/43-swiss-army/plans/6-add-fast-mode.md +46 -0
- package/RAF/43-swiss-army/plans/7-config-preset.md +51 -0
- package/RAF/44-config-api-change/decisions.md +22 -0
- package/RAF/44-config-api-change/input.md +5 -0
- package/RAF/44-config-api-change/outcomes/1-restructure-config-subcommands.md +19 -0
- package/RAF/44-config-api-change/outcomes/2-move-preset-under-config.md +17 -0
- package/RAF/44-config-api-change/outcomes/3-update-existing-tests-for-config-api.md +14 -0
- package/RAF/44-config-api-change/outcomes/4-update-config-command-docs.md +11 -0
- package/RAF/44-config-api-change/outcomes/5-fix-codex-name-generation.md +18 -0
- package/RAF/44-config-api-change/plans/1-restructure-config-subcommands.md +37 -0
- package/RAF/44-config-api-change/plans/2-move-preset-under-config.md +38 -0
- package/RAF/44-config-api-change/plans/3-update-existing-tests-for-config-api.md +38 -0
- package/RAF/44-config-api-change/plans/4-update-config-command-docs.md +36 -0
- package/RAF/44-config-api-change/plans/5-fix-codex-name-generation.md +49 -0
- package/RAF/45-signal-cairn/decisions.md +7 -0
- package/RAF/45-signal-cairn/input.md +2 -0
- package/RAF/45-signal-cairn/outcomes/1-rename-provider-to-harness.md +19 -0
- package/RAF/45-signal-cairn/outcomes/2-normalize-model-display-names.md +18 -0
- package/RAF/45-signal-cairn/plans/1-rename-provider-to-harness.md +40 -0
- package/RAF/45-signal-cairn/plans/2-normalize-model-display-names.md +41 -0
- package/RAF/45-signal-lantern/decisions.md +10 -0
- package/RAF/45-signal-lantern/input.md +2 -0
- package/RAF/45-signal-lantern/outcomes/1-add-effort-and-fast-to-do-model-display.md +15 -0
- package/RAF/45-signal-lantern/outcomes/2-capture-codex-post-run-token-usage.md +15 -0
- package/RAF/45-signal-lantern/outcomes/3-show-codex-token-summaries-without-fake-cost.md +14 -0
- package/RAF/45-signal-lantern/plans/1-add-effort-and-fast-to-do-model-display.md +38 -0
- package/RAF/45-signal-lantern/plans/2-capture-codex-post-run-token-usage.md +37 -0
- package/RAF/45-signal-lantern/plans/3-show-codex-token-summaries-without-fake-cost.md +40 -0
- package/RAF/46-lantern-arc/decisions.md +19 -0
- package/RAF/46-lantern-arc/input.md +6 -0
- package/RAF/46-lantern-arc/outcomes/1-remove-spark-alias.md +16 -0
- package/RAF/46-lantern-arc/outcomes/2-clean-up-worktree-plan-command.md +30 -0
- package/RAF/46-lantern-arc/outcomes/3-fix-token-usage-accumulation.md +32 -0
- package/RAF/46-lantern-arc/outcomes/4-display-effort-in-compact-mode.md +22 -0
- package/RAF/46-lantern-arc/outcomes/5-codex-fast-mode-research.md +38 -0
- package/RAF/46-lantern-arc/outcomes/6-optimize-llm-prompts.md +39 -0
- package/RAF/46-lantern-arc/plans/1-remove-spark-alias.md +38 -0
- package/RAF/46-lantern-arc/plans/2-clean-up-worktree-plan-command.md +33 -0
- package/RAF/46-lantern-arc/plans/3-fix-token-usage-accumulation.md +33 -0
- package/RAF/46-lantern-arc/plans/4-display-effort-in-compact-mode.md +28 -0
- package/RAF/46-lantern-arc/plans/5-codex-fast-mode-research.md +34 -0
- package/RAF/46-lantern-arc/plans/6-optimize-llm-prompts.md +48 -0
- package/RAF/47-signal-trim/decisions.md +13 -0
- package/RAF/47-signal-trim/input.md +2 -0
- package/RAF/47-signal-trim/plans/1-remove-cache-from-status.md +73 -0
- package/README.md +50 -63
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +47 -49
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/do.d.ts +2 -0
- package/dist/commands/do.d.ts.map +1 -1
- package/dist/commands/do.js +91 -230
- package/dist/commands/do.js.map +1 -1
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +54 -259
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/preset.d.ts +3 -0
- package/dist/commands/preset.d.ts.map +1 -0
- package/dist/commands/preset.js +158 -0
- package/dist/commands/preset.js.map +1 -0
- package/dist/core/claude-runner.d.ts +2 -0
- package/dist/core/claude-runner.d.ts.map +1 -1
- package/dist/core/claude-runner.js +36 -12
- package/dist/core/claude-runner.js.map +1 -1
- package/dist/core/codex-runner.d.ts +1 -0
- package/dist/core/codex-runner.d.ts.map +1 -1
- package/dist/core/codex-runner.js +26 -7
- package/dist/core/codex-runner.js.map +1 -1
- package/dist/core/failure-analyzer.js +2 -1
- package/dist/core/failure-analyzer.js.map +1 -1
- package/dist/core/git.d.ts +2 -2
- package/dist/core/git.d.ts.map +1 -1
- package/dist/core/git.js +53 -3
- package/dist/core/git.js.map +1 -1
- package/dist/core/project-manager.d.ts.map +1 -1
- package/dist/core/project-manager.js +2 -2
- package/dist/core/project-manager.js.map +1 -1
- package/dist/core/pull-request.js +5 -5
- package/dist/core/pull-request.js.map +1 -1
- package/dist/core/runner-factory.d.ts +4 -4
- package/dist/core/runner-factory.d.ts.map +1 -1
- package/dist/core/runner-factory.js +8 -8
- package/dist/core/runner-factory.js.map +1 -1
- package/dist/core/runner-interface.d.ts +1 -1
- package/dist/core/runner-types.d.ts +17 -4
- package/dist/core/runner-types.d.ts.map +1 -1
- package/dist/core/state-derivation.js +3 -3
- package/dist/core/state-derivation.js.map +1 -1
- package/dist/parsers/codex-stream-renderer.d.ts +28 -4
- package/dist/parsers/codex-stream-renderer.d.ts.map +1 -1
- package/dist/parsers/codex-stream-renderer.js +110 -0
- package/dist/parsers/codex-stream-renderer.js.map +1 -1
- package/dist/prompts/amend.d.ts +0 -1
- package/dist/prompts/amend.d.ts.map +1 -1
- package/dist/prompts/amend.js +31 -104
- package/dist/prompts/amend.js.map +1 -1
- package/dist/prompts/execution.d.ts.map +1 -1
- package/dist/prompts/execution.js +17 -34
- package/dist/prompts/execution.js.map +1 -1
- package/dist/prompts/planning.d.ts.map +1 -1
- package/dist/prompts/planning.js +23 -123
- package/dist/prompts/planning.js.map +1 -1
- package/dist/types/config.d.ts +33 -32
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +14 -28
- package/dist/types/config.js.map +1 -1
- package/dist/utils/config.d.ts +36 -16
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +209 -104
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/name-generator.d.ts.map +1 -1
- package/dist/utils/name-generator.js +25 -12
- package/dist/utils/name-generator.js.map +1 -1
- package/dist/utils/paths.d.ts +5 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +9 -0
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/terminal-symbols.d.ts +15 -2
- package/dist/utils/terminal-symbols.d.ts.map +1 -1
- package/dist/utils/terminal-symbols.js +36 -4
- package/dist/utils/terminal-symbols.js.map +1 -1
- package/dist/utils/token-tracker.d.ts +6 -1
- package/dist/utils/token-tracker.d.ts.map +1 -1
- package/dist/utils/token-tracker.js +84 -51
- package/dist/utils/token-tracker.js.map +1 -1
- package/dist/utils/validation.d.ts +1 -2
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +4 -25
- package/dist/utils/validation.js.map +1 -1
- package/package.json +7 -2
- package/src/commands/config.ts +60 -63
- package/src/commands/do.ts +96 -262
- package/src/commands/plan.ts +55 -279
- package/src/commands/preset.ts +186 -0
- package/src/core/claude-runner.ts +45 -5
- package/src/core/codex-runner.ts +32 -7
- package/src/core/failure-analyzer.ts +2 -1
- package/src/core/git.ts +57 -3
- package/src/core/project-manager.ts +2 -1
- package/src/core/pull-request.ts +5 -5
- package/src/core/runner-factory.ts +9 -9
- package/src/core/runner-interface.ts +1 -1
- package/src/core/runner-types.ts +17 -4
- package/src/core/state-derivation.ts +3 -3
- package/src/parsers/codex-stream-renderer.ts +149 -4
- package/src/prompts/amend.ts +30 -105
- package/src/prompts/config-docs.md +206 -62
- package/src/prompts/execution.ts +17 -34
- package/src/prompts/planning.ts +23 -124
- package/src/types/config.ts +47 -59
- package/src/utils/config.ts +248 -115
- package/src/utils/name-generator.ts +29 -13
- package/src/utils/paths.ts +10 -0
- package/src/utils/terminal-symbols.ts +46 -6
- package/src/utils/token-tracker.ts +96 -57
- package/src/utils/validation.ts +5 -30
- package/tests/unit/amend-prompt.test.ts +3 -2
- package/tests/unit/claude-runner-interactive.test.ts +21 -3
- package/tests/unit/claude-runner.test.ts +39 -0
- package/tests/unit/codex-runner.test.ts +163 -0
- package/tests/unit/codex-stream-renderer.test.ts +127 -0
- package/tests/unit/command-output.test.ts +57 -0
- package/tests/unit/commit-planning-artifacts-worktree.test.ts +24 -7
- package/tests/unit/commit-planning-artifacts.test.ts +26 -4
- package/tests/unit/config-command.test.ts +215 -303
- package/tests/unit/config.test.ts +319 -235
- package/tests/unit/dependency-integration.test.ts +27 -1
- package/tests/unit/do-model-display.test.ts +35 -0
- package/tests/unit/execution-prompt.test.ts +49 -19
- package/tests/unit/name-generator.test.ts +82 -12
- package/tests/unit/plan-command-auto-flag.test.ts +7 -10
- package/tests/unit/plan-command.test.ts +14 -17
- package/tests/unit/planning-prompt.test.ts +9 -8
- package/tests/unit/terminal-symbols.test.ts +94 -3
- package/tests/unit/token-tracker.test.ts +180 -1
- package/tests/unit/validation.test.ts +9 -41
- package/tests/unit/worktree-flag-override.test.ts +0 -186
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
1
2
|
import * as fs from 'node:fs';
|
|
2
3
|
import * as path from 'node:path';
|
|
3
4
|
import * as os from 'node:os';
|
|
@@ -13,7 +14,25 @@ import {
|
|
|
13
14
|
type DerivedTask,
|
|
14
15
|
} from '../../src/core/state-derivation.js';
|
|
15
16
|
import { getOutcomeFilePath, extractTaskNameFromPlanFile } from '../../src/utils/paths.js';
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
const suiteHomeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'raf-dependency-home-'));
|
|
19
|
+
let mockHomeDir = suiteHomeDir;
|
|
20
|
+
|
|
21
|
+
jest.unstable_mockModule('node:os', () => ({
|
|
22
|
+
homedir: () => mockHomeDir,
|
|
23
|
+
tmpdir: () => os.tmpdir(),
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
jest.unstable_mockModule('../../src/utils/config.js', () => ({
|
|
27
|
+
getCommitFormat: () => '{prefix}[{projectName}:{taskId}] {description}',
|
|
28
|
+
getCommitPrefix: () => 'RAF',
|
|
29
|
+
renderCommitMessage: (template: string, variables: Record<string, string>) =>
|
|
30
|
+
template.replace(/\{(\w+)\}/g, (match, key: string) => variables[key] ?? match),
|
|
31
|
+
resetConfigCache: jest.fn(),
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
const { getExecutionPrompt } = await import('../../src/prompts/execution.js');
|
|
35
|
+
const { resetConfigCache } = await import('../../src/utils/config.js');
|
|
17
36
|
|
|
18
37
|
/**
|
|
19
38
|
* Integration tests for the complete dependency blocking flow.
|
|
@@ -25,6 +44,8 @@ describe('Dependency Integration Flow', () => {
|
|
|
25
44
|
let projectPath: string;
|
|
26
45
|
|
|
27
46
|
beforeEach(() => {
|
|
47
|
+
fs.rmSync(path.join(mockHomeDir, '.raf'), { recursive: true, force: true });
|
|
48
|
+
resetConfigCache();
|
|
28
49
|
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'raf-dep-integration-'));
|
|
29
50
|
projectPath = path.join(tempDir, '1-test-project');
|
|
30
51
|
fs.mkdirSync(projectPath, { recursive: true });
|
|
@@ -34,9 +55,14 @@ describe('Dependency Integration Flow', () => {
|
|
|
34
55
|
});
|
|
35
56
|
|
|
36
57
|
afterEach(() => {
|
|
58
|
+
resetConfigCache();
|
|
37
59
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
38
60
|
});
|
|
39
61
|
|
|
62
|
+
afterAll(() => {
|
|
63
|
+
fs.rmSync(suiteHomeDir, { recursive: true, force: true });
|
|
64
|
+
});
|
|
65
|
+
|
|
40
66
|
describe('Complete dependency chain simulation', () => {
|
|
41
67
|
/**
|
|
42
68
|
* Simulates a real project with the following dependency structure:
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { formatResolvedTaskModel } from '../../src/commands/do.js';
|
|
2
|
+
import type { ModelEntry } from '../../src/types/config.js';
|
|
3
|
+
|
|
4
|
+
describe('do model display', () => {
|
|
5
|
+
it('should include effort and fast metadata in verbose model logs', () => {
|
|
6
|
+
const entry: ModelEntry = {
|
|
7
|
+
model: 'sonnet',
|
|
8
|
+
provider: 'claude',
|
|
9
|
+
reasoningEffort: 'low',
|
|
10
|
+
fast: true,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
expect(formatResolvedTaskModel(entry)).toBe('claude-sonnet-4-5-20250929, low, fast');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should omit effort when unavailable', () => {
|
|
17
|
+
const entry: ModelEntry = {
|
|
18
|
+
model: 'sonnet',
|
|
19
|
+
provider: 'claude',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
expect(formatResolvedTaskModel(entry)).toBe('claude-sonnet-4-5-20250929');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should omit fast when false', () => {
|
|
26
|
+
const entry: ModelEntry = {
|
|
27
|
+
model: 'sonnet',
|
|
28
|
+
provider: 'claude',
|
|
29
|
+
reasoningEffort: 'low',
|
|
30
|
+
fast: false,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
expect(formatResolvedTaskModel(entry)).toBe('claude-sonnet-4-5-20250929, low');
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -1,6 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import type { ExecutionPromptParams } from '../../src/prompts/execution.js';
|
|
6
|
+
|
|
7
|
+
const suiteHomeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'raf-execution-prompt-home-'));
|
|
8
|
+
let mockHomeDir = suiteHomeDir;
|
|
9
|
+
|
|
10
|
+
jest.unstable_mockModule('node:os', () => ({
|
|
11
|
+
homedir: () => mockHomeDir,
|
|
12
|
+
tmpdir: () => os.tmpdir(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
const { getExecutionPrompt, summarizeOutcome } = await import('../../src/prompts/execution.js');
|
|
16
|
+
const { resetConfigCache } = await import('../../src/utils/config.js');
|
|
2
17
|
|
|
3
18
|
describe('Execution Prompt', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
fs.rmSync(path.join(mockHomeDir, '.raf'), { recursive: true, force: true });
|
|
21
|
+
resetConfigCache();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
resetConfigCache();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterAll(() => {
|
|
29
|
+
fs.rmSync(suiteHomeDir, { recursive: true, force: true });
|
|
30
|
+
});
|
|
31
|
+
|
|
4
32
|
const baseParams: ExecutionPromptParams = {
|
|
5
33
|
projectPath: '/Users/test/RAF/42-task-naming-improvements',
|
|
6
34
|
planPath: '/Users/test/RAF/42-task-naming-improvements/plans/1-enhance-identifier-resolution.md',
|
|
@@ -16,7 +44,7 @@ describe('Execution Prompt', () => {
|
|
|
16
44
|
describe('Commit Message Format', () => {
|
|
17
45
|
it('should include RAF commit schema format with description placeholder in prompt', () => {
|
|
18
46
|
const prompt = getExecutionPrompt(baseParams);
|
|
19
|
-
expect(prompt).toContain('RAF[
|
|
47
|
+
expect(prompt).toContain('RAF[task-naming-improvements:1] <description>');
|
|
20
48
|
});
|
|
21
49
|
|
|
22
50
|
it('should instruct to write meaningful description', () => {
|
|
@@ -28,25 +56,25 @@ describe('Execution Prompt', () => {
|
|
|
28
56
|
it('should use plain numeric task IDs', () => {
|
|
29
57
|
const params = { ...baseParams, taskNumber: 1 };
|
|
30
58
|
const prompt = getExecutionPrompt(params);
|
|
31
|
-
expect(prompt).toContain('RAF[
|
|
59
|
+
expect(prompt).toContain('RAF[task-naming-improvements:1]');
|
|
32
60
|
});
|
|
33
61
|
|
|
34
62
|
it('should use numeric task IDs for double digits', () => {
|
|
35
63
|
const params = { ...baseParams, taskNumber: 12 };
|
|
36
64
|
const prompt = getExecutionPrompt(params);
|
|
37
|
-
expect(prompt).toContain('RAF[
|
|
65
|
+
expect(prompt).toContain('RAF[task-naming-improvements:12]');
|
|
38
66
|
});
|
|
39
67
|
|
|
40
68
|
it('should use numeric task IDs for large numbers', () => {
|
|
41
69
|
const params = { ...baseParams, taskNumber: 123 };
|
|
42
70
|
const prompt = getExecutionPrompt(params);
|
|
43
|
-
expect(prompt).toContain('RAF[
|
|
71
|
+
expect(prompt).toContain('RAF[task-naming-improvements:123]');
|
|
44
72
|
});
|
|
45
73
|
|
|
46
|
-
it('should
|
|
47
|
-
const params = { ...baseParams, projectNumber: '7' };
|
|
74
|
+
it('should use project name from folder in commit format', () => {
|
|
75
|
+
const params = { ...baseParams, projectPath: '/Users/test/RAF/7-auth-fix', projectNumber: '7' };
|
|
48
76
|
const prompt = getExecutionPrompt(params);
|
|
49
|
-
expect(prompt).toContain('RAF[
|
|
77
|
+
expect(prompt).toContain('RAF[auth-fix:1]');
|
|
50
78
|
});
|
|
51
79
|
|
|
52
80
|
it('should not include commit instructions when autoCommit is false', () => {
|
|
@@ -67,7 +95,9 @@ describe('Execution Prompt', () => {
|
|
|
67
95
|
const params = { ...baseParams, autoCommit: false };
|
|
68
96
|
const prompt = getExecutionPrompt(params);
|
|
69
97
|
expect(prompt).not.toContain('On Failure');
|
|
70
|
-
|
|
98
|
+
// The general outcome section still mentions not committing on failure,
|
|
99
|
+
// but the git-specific instructions block should be absent
|
|
100
|
+
expect(prompt).not.toContain('Git Instructions');
|
|
71
101
|
});
|
|
72
102
|
|
|
73
103
|
it('should instruct not to add Co-Authored-By or other trailers', () => {
|
|
@@ -96,7 +126,7 @@ describe('Execution Prompt', () => {
|
|
|
96
126
|
outcomeFilePath: '/Users/test/RAF/42-task-naming-improvements/outcomes/6-update-execution-prompt.md',
|
|
97
127
|
};
|
|
98
128
|
const prompt = getExecutionPrompt(params);
|
|
99
|
-
expect(prompt).toContain('RAF[
|
|
129
|
+
expect(prompt).toContain('RAF[task-naming-improvements:6] <description>');
|
|
100
130
|
});
|
|
101
131
|
|
|
102
132
|
it('should generate correct commit message format for first task', () => {
|
|
@@ -112,7 +142,7 @@ describe('Execution Prompt', () => {
|
|
|
112
142
|
outcomeFilePath: '/Users/test/RAF/1-fix-bug/outcomes/1-identify-issue.md',
|
|
113
143
|
};
|
|
114
144
|
const prompt = getExecutionPrompt(params);
|
|
115
|
-
expect(prompt).toContain('RAF[
|
|
145
|
+
expect(prompt).toContain('RAF[fix-bug:1] <description>');
|
|
116
146
|
});
|
|
117
147
|
|
|
118
148
|
it('should generate correct commit message format for numeric project', () => {
|
|
@@ -128,7 +158,7 @@ describe('Execution Prompt', () => {
|
|
|
128
158
|
outcomeFilePath: '/Users/test/RAF/7-feature-branch/outcomes/2-implement-feature.md',
|
|
129
159
|
};
|
|
130
160
|
const prompt = getExecutionPrompt(params);
|
|
131
|
-
expect(prompt).toContain('RAF[
|
|
161
|
+
expect(prompt).toContain('RAF[feature-branch:2] <description>');
|
|
132
162
|
});
|
|
133
163
|
});
|
|
134
164
|
|
|
@@ -163,7 +193,7 @@ describe('Execution Prompt', () => {
|
|
|
163
193
|
|
|
164
194
|
it('should include instructions for writing outcome file', () => {
|
|
165
195
|
const prompt = getExecutionPrompt(baseParams);
|
|
166
|
-
expect(prompt).toContain('
|
|
196
|
+
expect(prompt).toContain('Outcome file path');
|
|
167
197
|
expect(prompt).toContain('summary of what was done');
|
|
168
198
|
});
|
|
169
199
|
|
|
@@ -176,25 +206,25 @@ describe('Execution Prompt', () => {
|
|
|
176
206
|
|
|
177
207
|
it('should distinguish between code tasks and documentation tasks', () => {
|
|
178
208
|
const prompt = getExecutionPrompt(baseParams);
|
|
179
|
-
expect(prompt).toContain('
|
|
180
|
-
expect(prompt).toContain('For documentation/report tasks');
|
|
209
|
+
expect(prompt).toContain('documentation/report tasks');
|
|
181
210
|
});
|
|
182
211
|
|
|
183
212
|
it('should instruct that marker is last line in outcome file', () => {
|
|
184
213
|
const prompt = getExecutionPrompt(baseParams);
|
|
185
|
-
expect(prompt).toContain('completion marker
|
|
214
|
+
expect(prompt).toContain('completion marker as the LAST line');
|
|
186
215
|
});
|
|
187
216
|
});
|
|
188
217
|
|
|
189
218
|
describe('Commit Workflow Rules', () => {
|
|
190
|
-
it('should include
|
|
219
|
+
it('should include commit instructions when autoCommit is true', () => {
|
|
191
220
|
const prompt = getExecutionPrompt(baseParams);
|
|
192
|
-
expect(prompt).toContain('
|
|
221
|
+
expect(prompt).toContain('Git Instructions');
|
|
222
|
+
expect(prompt).toContain('git add');
|
|
193
223
|
});
|
|
194
224
|
|
|
195
225
|
it('should include rule not to commit on failure', () => {
|
|
196
226
|
const prompt = getExecutionPrompt(baseParams);
|
|
197
|
-
expect(prompt).toContain('
|
|
227
|
+
expect(prompt).toContain('do NOT commit');
|
|
198
228
|
});
|
|
199
229
|
|
|
200
230
|
it('should specify that changes are preserved for debugging on failure', () => {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { jest } from '@jest/globals';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
+
import type { HarnessName } from '../../src/types/config.js';
|
|
4
|
+
|
|
5
|
+
let currentNameGenerationModel = {
|
|
6
|
+
model: 'sonnet',
|
|
7
|
+
harness: 'claude' as HarnessName,
|
|
8
|
+
};
|
|
3
9
|
|
|
4
10
|
// Helper to create a mock spawn that returns a fake ChildProcess
|
|
5
11
|
function createMockSpawn(stdoutData: string | null, exitCode: number = 0) {
|
|
@@ -28,6 +34,11 @@ jest.unstable_mockModule('node:child_process', () => ({
|
|
|
28
34
|
execSync: jest.fn(), // keep available for transitive imports
|
|
29
35
|
}));
|
|
30
36
|
|
|
37
|
+
jest.unstable_mockModule('../../src/utils/config.js', () => ({
|
|
38
|
+
getModel: jest.fn(() => currentNameGenerationModel),
|
|
39
|
+
isValidModelName: jest.fn(() => true),
|
|
40
|
+
}));
|
|
41
|
+
|
|
31
42
|
// Import after mocking
|
|
32
43
|
const { generateProjectName, generateProjectNames, sanitizeGeneratedName } =
|
|
33
44
|
await import('../../src/utils/name-generator.js');
|
|
@@ -35,10 +46,14 @@ const { generateProjectName, generateProjectNames, sanitizeGeneratedName } =
|
|
|
35
46
|
describe('Name Generator', () => {
|
|
36
47
|
beforeEach(() => {
|
|
37
48
|
jest.clearAllMocks();
|
|
49
|
+
currentNameGenerationModel = {
|
|
50
|
+
model: 'sonnet',
|
|
51
|
+
harness: 'claude',
|
|
52
|
+
};
|
|
38
53
|
});
|
|
39
54
|
|
|
40
55
|
describe('generateProjectName', () => {
|
|
41
|
-
it('should return sanitized name from
|
|
56
|
+
it('should return sanitized name from CLI response', async () => {
|
|
42
57
|
mockSpawn.mockReturnValue(createMockSpawn('user-auth-system\n'));
|
|
43
58
|
|
|
44
59
|
const result = await generateProjectName('Build a user authentication system');
|
|
@@ -46,8 +61,8 @@ describe('Name Generator', () => {
|
|
|
46
61
|
expect(result).toBe('user-auth-system');
|
|
47
62
|
expect(mockSpawn).toHaveBeenCalledTimes(1);
|
|
48
63
|
expect(mockSpawn).toHaveBeenCalledWith(
|
|
49
|
-
|
|
50
|
-
expect.arrayContaining(['--model',
|
|
64
|
+
currentNameGenerationModel.harness,
|
|
65
|
+
expect.arrayContaining(['--model', currentNameGenerationModel.model, '--no-session-persistence', '-p']),
|
|
51
66
|
expect.any(Object)
|
|
52
67
|
);
|
|
53
68
|
});
|
|
@@ -77,7 +92,7 @@ describe('Name Generator', () => {
|
|
|
77
92
|
expect(result).toBe('some-project-name');
|
|
78
93
|
});
|
|
79
94
|
|
|
80
|
-
it('should fall back to word extraction when
|
|
95
|
+
it('should fall back to word extraction when CLI fails', async () => {
|
|
81
96
|
mockSpawn.mockReturnValue(createMockSpawn(null, 1));
|
|
82
97
|
|
|
83
98
|
const result = await generateProjectName('Build a user authentication system with OAuth');
|
|
@@ -85,7 +100,7 @@ describe('Name Generator', () => {
|
|
|
85
100
|
expect(result).toBe('build-user-authentication');
|
|
86
101
|
});
|
|
87
102
|
|
|
88
|
-
it('should fall back to word extraction when
|
|
103
|
+
it('should fall back to word extraction when CLI returns empty', async () => {
|
|
89
104
|
mockSpawn.mockReturnValue(createMockSpawn(''));
|
|
90
105
|
|
|
91
106
|
const result = await generateProjectName('Implement caching layer for database');
|
|
@@ -93,7 +108,7 @@ describe('Name Generator', () => {
|
|
|
93
108
|
expect(result).toBe('implement-caching-layer');
|
|
94
109
|
});
|
|
95
110
|
|
|
96
|
-
it('should fall back to word extraction when
|
|
111
|
+
it('should fall back to word extraction when CLI returns single char', async () => {
|
|
97
112
|
mockSpawn.mockReturnValue(createMockSpawn('a'));
|
|
98
113
|
|
|
99
114
|
const result = await generateProjectName('Add new logging functionality');
|
|
@@ -109,7 +124,7 @@ describe('Name Generator', () => {
|
|
|
109
124
|
expect(result).toBe('project');
|
|
110
125
|
});
|
|
111
126
|
|
|
112
|
-
it('should truncate long names from
|
|
127
|
+
it('should truncate long names from CLI', async () => {
|
|
113
128
|
const longName =
|
|
114
129
|
'this-is-a-very-long-project-name-that-exceeds-the-maximum-allowed-length-for-folder-names';
|
|
115
130
|
mockSpawn.mockReturnValue(createMockSpawn(longName));
|
|
@@ -153,7 +168,7 @@ describe('Name Generator', () => {
|
|
|
153
168
|
});
|
|
154
169
|
|
|
155
170
|
describe('generateProjectNames', () => {
|
|
156
|
-
it('should return multiple sanitized names from
|
|
171
|
+
it('should return multiple sanitized names from CLI response', async () => {
|
|
157
172
|
mockSpawn.mockReturnValue(
|
|
158
173
|
createMockSpawn('phoenix-rise\nturbo-boost\nbug-squasher\ncatalyst\nmerlin\n')
|
|
159
174
|
);
|
|
@@ -227,7 +242,7 @@ describe('Name Generator', () => {
|
|
|
227
242
|
expect(result.length).toBe(3);
|
|
228
243
|
});
|
|
229
244
|
|
|
230
|
-
it('should fall back to single name when
|
|
245
|
+
it('should fall back to single name when CLI fails', async () => {
|
|
231
246
|
mockSpawn.mockReturnValue(createMockSpawn(null, 1));
|
|
232
247
|
|
|
233
248
|
const result = await generateProjectNames('Build a user authentication system with OAuth');
|
|
@@ -235,13 +250,12 @@ describe('Name Generator', () => {
|
|
|
235
250
|
expect(result).toEqual(['build-user-authentication']);
|
|
236
251
|
});
|
|
237
252
|
|
|
238
|
-
it('should
|
|
253
|
+
it('should keep 1-2 valid names instead of falling back', async () => {
|
|
239
254
|
mockSpawn.mockReturnValue(createMockSpawn('phoenix\nturbo\n'));
|
|
240
255
|
|
|
241
256
|
const result = await generateProjectNames('Build something awesome');
|
|
242
257
|
|
|
243
|
-
|
|
244
|
-
expect(result).toEqual(['build-something-awesome']);
|
|
258
|
+
expect(result).toEqual(['phoenix', 'turbo']);
|
|
245
259
|
});
|
|
246
260
|
|
|
247
261
|
it('should filter out invalid/short names', async () => {
|
|
@@ -271,6 +285,62 @@ describe('Name Generator', () => {
|
|
|
271
285
|
|
|
272
286
|
expect(result).toEqual(['some-project']);
|
|
273
287
|
});
|
|
288
|
+
|
|
289
|
+
it('should fall back when codex returns no usable suggestions after sanitization', async () => {
|
|
290
|
+
currentNameGenerationModel = {
|
|
291
|
+
model: 'gpt-5.4',
|
|
292
|
+
harness: 'codex',
|
|
293
|
+
};
|
|
294
|
+
mockSpawn.mockReturnValue(createMockSpawn('a\n!\n'));
|
|
295
|
+
|
|
296
|
+
const result = await generateProjectNames('Build something awesome');
|
|
297
|
+
|
|
298
|
+
expect(result).toEqual(['build-something-awesome']);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should no longer accept a harness argument (config-driven)', async () => {
|
|
302
|
+
// The harness is embedded in the config, not passed as a parameter
|
|
303
|
+
// This test verifies that generateProjectNames has a single-parameter signature
|
|
304
|
+
mockSpawn.mockReturnValue(
|
|
305
|
+
createMockSpawn('phoenix\nturbo-boost\ncatalyst\n')
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
const result = await generateProjectNames('Build something');
|
|
309
|
+
|
|
310
|
+
expect(result).toEqual(['phoenix', 'turbo-boost', 'catalyst']);
|
|
311
|
+
expect(mockSpawn).toHaveBeenCalledWith(
|
|
312
|
+
currentNameGenerationModel.harness,
|
|
313
|
+
expect.arrayContaining(['--model', currentNameGenerationModel.model]),
|
|
314
|
+
expect.any(Object)
|
|
315
|
+
);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('should use codex exec invocation for name generation when configured', async () => {
|
|
319
|
+
currentNameGenerationModel = {
|
|
320
|
+
model: 'gpt-5.4',
|
|
321
|
+
harness: 'codex',
|
|
322
|
+
};
|
|
323
|
+
mockSpawn.mockReturnValue(createMockSpawn('phoenix-rise\nturbo-boost\nbug-squasher\n'));
|
|
324
|
+
|
|
325
|
+
const result = await generateProjectNames('Build something');
|
|
326
|
+
|
|
327
|
+
expect(result).toEqual(['phoenix-rise', 'turbo-boost', 'bug-squasher']);
|
|
328
|
+
expect(mockSpawn).toHaveBeenCalledWith(
|
|
329
|
+
'codex',
|
|
330
|
+
expect.arrayContaining([
|
|
331
|
+
'exec',
|
|
332
|
+
'--skip-git-repo-check',
|
|
333
|
+
'--ephemeral',
|
|
334
|
+
'--color',
|
|
335
|
+
'never',
|
|
336
|
+
'-m',
|
|
337
|
+
'gpt-5.4',
|
|
338
|
+
]),
|
|
339
|
+
expect.any(Object)
|
|
340
|
+
);
|
|
341
|
+
const promptArg = (mockSpawn.mock.calls[0][1] as string[]).at(-1);
|
|
342
|
+
expect(promptArg).toContain('Output EXACTLY 5 project names');
|
|
343
|
+
});
|
|
274
344
|
});
|
|
275
345
|
|
|
276
346
|
describe('sanitizeGeneratedName', () => {
|
|
@@ -52,26 +52,23 @@ describe('Plan Command - Auto Flag', () => {
|
|
|
52
52
|
expect(amendOption).toBeDefined();
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
it('should
|
|
55
|
+
it('should not have --provider flag (removed)', () => {
|
|
56
56
|
const command = createPlanCommand();
|
|
57
57
|
const options = command.options;
|
|
58
58
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
expect(autoOption).toBeDefined();
|
|
63
|
-
expect(modelOption).toBeDefined();
|
|
59
|
+
const providerOption = options.find((opt) => opt.long === '--provider');
|
|
60
|
+
expect(providerOption).toBeUndefined();
|
|
64
61
|
});
|
|
65
62
|
|
|
66
|
-
it('should
|
|
63
|
+
it('should not have removed --model or --sonnet flags', () => {
|
|
67
64
|
const command = createPlanCommand();
|
|
68
65
|
const options = command.options;
|
|
69
66
|
|
|
70
|
-
const
|
|
67
|
+
const modelOption = options.find((opt) => opt.long === '--model');
|
|
71
68
|
const sonnetOption = options.find((opt) => opt.long === '--sonnet');
|
|
72
69
|
|
|
73
|
-
expect(
|
|
74
|
-
expect(sonnetOption).
|
|
70
|
+
expect(modelOption).toBeUndefined();
|
|
71
|
+
expect(sonnetOption).toBeUndefined();
|
|
75
72
|
});
|
|
76
73
|
});
|
|
77
74
|
|
|
@@ -344,10 +344,10 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
344
344
|
|
|
345
345
|
const { systemPrompt } = getAmendPrompt(params);
|
|
346
346
|
|
|
347
|
-
expect(systemPrompt).toContain('
|
|
347
|
+
expect(systemPrompt).toContain('Amendment Mode');
|
|
348
348
|
expect(systemPrompt).toContain('Task 1: first [COMPLETED] [PROTECTED]');
|
|
349
349
|
expect(systemPrompt).toContain('Task 2: second [PENDING] [MODIFIABLE]');
|
|
350
|
-
expect(systemPrompt).toContain('
|
|
350
|
+
expect(systemPrompt).toContain('start from number 3');
|
|
351
351
|
expect(systemPrompt).toContain('/test/project');
|
|
352
352
|
});
|
|
353
353
|
|
|
@@ -377,11 +377,9 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
377
377
|
|
|
378
378
|
const { systemPrompt } = getAmendPrompt(params);
|
|
379
379
|
|
|
380
|
-
expect(systemPrompt).toContain('
|
|
381
|
-
expect(systemPrompt).toContain('
|
|
382
|
-
expect(systemPrompt).toContain('
|
|
383
|
-
expect(systemPrompt).toContain('NEVER modify COMPLETED task plans - they are [PROTECTED]');
|
|
384
|
-
expect(systemPrompt).toContain('You MAY modify non-completed task plans (pending/failed)');
|
|
380
|
+
expect(systemPrompt).toContain('[PROTECTED] tasks (completed): NEVER modify');
|
|
381
|
+
expect(systemPrompt).toContain('Do NOT renumber existing tasks');
|
|
382
|
+
expect(systemPrompt).toContain('[MODIFIABLE] tasks (pending/failed): MAY modify');
|
|
385
383
|
});
|
|
386
384
|
|
|
387
385
|
it('should include failed task status with MODIFIABLE indicator in system prompt', () => {
|
|
@@ -413,7 +411,7 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
413
411
|
|
|
414
412
|
const { systemPrompt } = getAmendPrompt(params);
|
|
415
413
|
|
|
416
|
-
expect(systemPrompt).toContain('### Protected
|
|
414
|
+
expect(systemPrompt).toContain('### Protected (COMPLETED)');
|
|
417
415
|
expect(systemPrompt).toContain('- Task 1: first');
|
|
418
416
|
expect(systemPrompt).toContain('- Task 2: second');
|
|
419
417
|
});
|
|
@@ -432,7 +430,7 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
432
430
|
|
|
433
431
|
const { systemPrompt } = getAmendPrompt(params);
|
|
434
432
|
|
|
435
|
-
expect(systemPrompt).toContain('### Modifiable
|
|
433
|
+
expect(systemPrompt).toContain('### Modifiable (PENDING/FAILED)');
|
|
436
434
|
expect(systemPrompt).toContain('- Task 2: second');
|
|
437
435
|
expect(systemPrompt).toContain('- Task 3: third');
|
|
438
436
|
});
|
|
@@ -449,7 +447,7 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
449
447
|
|
|
450
448
|
const { systemPrompt } = getAmendPrompt(params);
|
|
451
449
|
|
|
452
|
-
expect(systemPrompt).toContain('### Protected
|
|
450
|
+
expect(systemPrompt).toContain('### Protected (COMPLETED)\n(none)');
|
|
453
451
|
});
|
|
454
452
|
|
|
455
453
|
it('should show (none) when there are no modifiable tasks', () => {
|
|
@@ -464,7 +462,7 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
464
462
|
|
|
465
463
|
const { systemPrompt } = getAmendPrompt(params);
|
|
466
464
|
|
|
467
|
-
expect(systemPrompt).toContain('### Modifiable
|
|
465
|
+
expect(systemPrompt).toContain('### Modifiable (PENDING/FAILED)\n(none)');
|
|
468
466
|
});
|
|
469
467
|
|
|
470
468
|
it('should handle mixed task statuses correctly', () => {
|
|
@@ -489,8 +487,8 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
489
487
|
expect(systemPrompt).toContain('Task 4: tests [PENDING] [MODIFIABLE]');
|
|
490
488
|
|
|
491
489
|
// Check separate lists
|
|
492
|
-
expect(systemPrompt).toContain('### Protected
|
|
493
|
-
expect(systemPrompt).toContain('### Modifiable
|
|
490
|
+
expect(systemPrompt).toContain('### Protected (COMPLETED)');
|
|
491
|
+
expect(systemPrompt).toContain('### Modifiable (PENDING/FAILED)');
|
|
494
492
|
});
|
|
495
493
|
|
|
496
494
|
it('should include correct plans directory path', () => {
|
|
@@ -506,7 +504,6 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
506
504
|
const { systemPrompt } = getAmendPrompt(params);
|
|
507
505
|
|
|
508
506
|
expect(systemPrompt).toContain('/my/project/path/plans/2-task-name.md');
|
|
509
|
-
expect(systemPrompt).toContain('/my/project/path/plans/3-task-name.md');
|
|
510
507
|
});
|
|
511
508
|
|
|
512
509
|
it('should include new task description in user message', () => {
|
|
@@ -532,7 +529,7 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
532
529
|
|
|
533
530
|
const { systemPrompt } = getAmendPrompt(params);
|
|
534
531
|
|
|
535
|
-
expect(systemPrompt).toContain('
|
|
532
|
+
expect(systemPrompt).toContain('Amendment Mode');
|
|
536
533
|
expect(systemPrompt).toContain('AskUserQuestion');
|
|
537
534
|
expect(systemPrompt).toContain('Interview the User');
|
|
538
535
|
});
|
|
@@ -597,9 +594,9 @@ describe('Plan Command - Amend Functionality', () => {
|
|
|
597
594
|
|
|
598
595
|
const { systemPrompt } = getAmendPrompt(params);
|
|
599
596
|
|
|
600
|
-
expect(systemPrompt).toContain('Identifying Follow-up Tasks');
|
|
601
597
|
expect(systemPrompt).toContain('follow-up to task NN');
|
|
602
|
-
expect(systemPrompt).toContain('
|
|
598
|
+
expect(systemPrompt).toContain('follow-up');
|
|
599
|
+
expect(systemPrompt).toContain('outcome');
|
|
603
600
|
});
|
|
604
601
|
});
|
|
605
602
|
|
|
@@ -76,8 +76,8 @@ describe('Planning Prompt', () => {
|
|
|
76
76
|
|
|
77
77
|
const { systemPrompt } = getPlanningPrompt(params);
|
|
78
78
|
|
|
79
|
-
expect(systemPrompt).toContain('/test/project/plans/
|
|
80
|
-
expect(systemPrompt).toContain('
|
|
79
|
+
expect(systemPrompt).toContain('/test/project/plans/');
|
|
80
|
+
expect(systemPrompt).toContain('1-task-name.md');
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
it('should include task guidelines in system prompt', () => {
|
|
@@ -88,7 +88,7 @@ describe('Planning Prompt', () => {
|
|
|
88
88
|
|
|
89
89
|
const { systemPrompt } = getPlanningPrompt(params);
|
|
90
90
|
|
|
91
|
-
expect(systemPrompt).toContain('
|
|
91
|
+
expect(systemPrompt).toContain('Identify distinct tasks');
|
|
92
92
|
expect(systemPrompt).toContain('independently completable');
|
|
93
93
|
expect(systemPrompt).toContain('10-30 minutes');
|
|
94
94
|
});
|
|
@@ -116,9 +116,9 @@ describe('Planning Prompt', () => {
|
|
|
116
116
|
|
|
117
117
|
const { systemPrompt } = getPlanningPrompt(params);
|
|
118
118
|
|
|
119
|
-
expect(systemPrompt).toContain('
|
|
120
|
-
expect(systemPrompt).toContain('
|
|
121
|
-
expect(systemPrompt).toContain('kebab-case
|
|
119
|
+
expect(systemPrompt).toContain('Do not skip this step');
|
|
120
|
+
expect(systemPrompt).toContain('execution order');
|
|
121
|
+
expect(systemPrompt).toContain('kebab-case');
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
it('should show raf do without --worktree when worktreeMode is false', () => {
|
|
@@ -146,7 +146,7 @@ describe('Planning Prompt', () => {
|
|
|
146
146
|
expect(systemPrompt).not.toContain('--worktree');
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
it('should show raf do
|
|
149
|
+
it('should show raf do without --worktree when worktreeMode is true', () => {
|
|
150
150
|
const params: PlanningPromptParams = {
|
|
151
151
|
projectPath: '/test/project',
|
|
152
152
|
inputContent: 'Some project',
|
|
@@ -155,7 +155,8 @@ describe('Planning Prompt', () => {
|
|
|
155
155
|
|
|
156
156
|
const { systemPrompt } = getPlanningPrompt(params);
|
|
157
157
|
|
|
158
|
-
expect(systemPrompt).toContain('raf do <project>
|
|
158
|
+
expect(systemPrompt).toContain('raf do <project>');
|
|
159
|
+
expect(systemPrompt).not.toContain('--worktree');
|
|
159
160
|
});
|
|
160
161
|
|
|
161
162
|
it('should include project description in user message', () => {
|