Enhance workflow commands and context management

- Updated `plan.md` to include new fields in context-package.json: prioritized_context, user_intent, priority_tiers, dependency_order, and sorting_rationale.
- Added validation for the existence of the prioritized_context field in context-package.json.
- Modified user decision flow in task generation to present action choices after planning completion.
- Improved context-gathering process in `context-gather.md` to integrate user intent and prioritize context based on user goals.
- Revised conflict-resolution documentation to require planning notes records after conflict analysis.
- Streamlined task generation in `task-generate-agent.md` to utilize pre-sorted context without redundant sorting.
- Removed unused settings persistence functions and corresponding tests from `claude-cli-tools.ts` and `settings-persistence.test.ts`.
This commit is contained in:
catlog22
2026-01-28 00:02:45 +08:00
parent 9989cfcf21
commit b3c47294e7
8 changed files with 744 additions and 1176 deletions

View File

@@ -733,66 +733,6 @@ export function getPromptFormat(projectDir: string): 'plain' | 'yaml' | 'json' {
}
}
/**
* Update default model setting
* @param projectDir - Project directory path
* @param model - Default model name
* @returns Updated settings config
*/
export function setDefaultModel(
projectDir: string,
model: string
): ClaudeCliSettingsConfig {
const settings = loadClaudeCliSettings(projectDir);
settings.defaultModel = model;
saveClaudeCliSettings(projectDir, settings);
return settings;
}
/**
* Get default model setting
* @param projectDir - Project directory path
* @returns Current default model or undefined if not set
*/
export function getDefaultModel(projectDir: string): string | undefined {
try {
const settings = loadClaudeCliSettings(projectDir);
return settings.defaultModel;
} catch {
return undefined;
}
}
/**
* Update auto-sync enabled setting
* @param projectDir - Project directory path
* @param enabled - Whether auto-sync is enabled
* @returns Updated settings config
*/
export function setAutoSyncEnabled(
projectDir: string,
enabled: boolean
): ClaudeCliSettingsConfig {
const settings = loadClaudeCliSettings(projectDir);
settings.autoSyncEnabled = enabled;
saveClaudeCliSettings(projectDir, settings);
return settings;
}
/**
* Get auto-sync enabled setting
* @param projectDir - Project directory path
* @returns Current auto-sync status or undefined if not set
*/
export function getAutoSyncEnabled(projectDir: string): boolean | undefined {
try {
const settings = loadClaudeCliSettings(projectDir);
return settings.autoSyncEnabled;
} catch {
return undefined;
}
}
/**
* Update smart context enabled setting
* @param projectDir - Project directory path

View File

@@ -1,375 +0,0 @@
/**
* Unit tests for Settings Persistence Functions
*
* Tests the new setter/getter functions for ClaudeCliSettingsConfig:
* - setPromptFormat / getPromptFormat
* - setDefaultModel / getDefaultModel
* - setAutoSyncEnabled / getAutoSyncEnabled
* - setSmartContextEnabled / getSmartContextEnabled
* - setNativeResume / getNativeResume
*/
import { after, afterEach, before, describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { existsSync, mkdtempSync, rmSync, writeFileSync, readFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
// Set up isolated test environment
const TEST_CCW_HOME = mkdtempSync(join(tmpdir(), 'ccw-settings-test-'));
process.env.CCW_DATA_DIR = TEST_CCW_HOME;
const claudeCliToolsPath = new URL('../dist/tools/claude-cli-tools.js', import.meta.url).href;
describe('Settings Persistence Functions', async () => {
let claudeCliTools: any;
const testProjectDir = join(TEST_CCW_HOME, 'test-project');
before(async () => {
claudeCliTools = await import(claudeCliToolsPath);
});
after(() => {
rmSync(TEST_CCW_HOME, { recursive: true, force: true });
});
afterEach(() => {
// Clean up settings file after each test
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
if (existsSync(settingsPath)) {
rmSync(settingsPath);
}
});
describe('setPromptFormat / getPromptFormat', () => {
it('should set and get prompt format', () => {
const result = claudeCliTools.setPromptFormat(testProjectDir, 'yaml');
assert.equal(result.promptFormat, 'yaml');
const retrieved = claudeCliTools.getPromptFormat(testProjectDir);
assert.equal(retrieved, 'yaml');
});
it('should persist prompt format to file', () => {
claudeCliTools.setPromptFormat(testProjectDir, 'json');
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
assert.ok(existsSync(settingsPath), 'Settings file should exist');
const content = JSON.parse(readFileSync(settingsPath, 'utf-8'));
assert.equal(content.promptFormat, 'json');
});
it('should update existing prompt format', () => {
claudeCliTools.setPromptFormat(testProjectDir, 'plain');
claudeCliTools.setPromptFormat(testProjectDir, 'yaml');
const retrieved = claudeCliTools.getPromptFormat(testProjectDir);
assert.equal(retrieved, 'yaml');
});
it('should return default when file does not exist', () => {
const retrieved = claudeCliTools.getPromptFormat(testProjectDir);
assert.equal(retrieved, 'plain');
});
it('should accept all valid format values', () => {
const formats: Array<'plain' | 'yaml' | 'json'> = ['plain', 'yaml', 'json'];
for (const format of formats) {
claudeCliTools.setPromptFormat(testProjectDir, format);
const retrieved = claudeCliTools.getPromptFormat(testProjectDir);
assert.equal(retrieved, format, `Format ${format} should be set correctly`);
}
});
});
describe('setDefaultModel / getDefaultModel', () => {
it('should set and get default model', () => {
const result = claudeCliTools.setDefaultModel(testProjectDir, 'gemini-2.5-pro');
assert.equal(result.defaultModel, 'gemini-2.5-pro');
const retrieved = claudeCliTools.getDefaultModel(testProjectDir);
assert.equal(retrieved, 'gemini-2.5-pro');
});
it('should persist default model to file', () => {
claudeCliTools.setDefaultModel(testProjectDir, 'claude-opus-4');
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
assert.ok(existsSync(settingsPath), 'Settings file should exist');
const content = JSON.parse(readFileSync(settingsPath, 'utf-8'));
assert.equal(content.defaultModel, 'claude-opus-4');
});
it('should update existing default model', () => {
claudeCliTools.setDefaultModel(testProjectDir, 'gpt-4.1');
claudeCliTools.setDefaultModel(testProjectDir, 'gpt-5.2');
const retrieved = claudeCliTools.getDefaultModel(testProjectDir);
assert.equal(retrieved, 'gpt-5.2');
});
it('should return undefined when not set', () => {
const retrieved = claudeCliTools.getDefaultModel(testProjectDir);
assert.equal(retrieved, undefined);
});
it('should handle arbitrary model names', () => {
const models = ['custom-model-1', 'test-model', 'my-fine-tuned-model'];
for (const model of models) {
claudeCliTools.setDefaultModel(testProjectDir, model);
const retrieved = claudeCliTools.getDefaultModel(testProjectDir);
assert.equal(retrieved, model, `Model ${model} should be set correctly`);
}
});
});
describe('setAutoSyncEnabled / getAutoSyncEnabled', () => {
it('should set and get auto-sync enabled status', () => {
const result = claudeCliTools.setAutoSyncEnabled(testProjectDir, true);
assert.equal(result.autoSyncEnabled, true);
const retrieved = claudeCliTools.getAutoSyncEnabled(testProjectDir);
assert.equal(retrieved, true);
});
it('should persist auto-sync status to file', () => {
claudeCliTools.setAutoSyncEnabled(testProjectDir, false);
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
assert.ok(existsSync(settingsPath), 'Settings file should exist');
const content = JSON.parse(readFileSync(settingsPath, 'utf-8'));
assert.equal(content.autoSyncEnabled, false);
});
it('should update existing auto-sync status', () => {
claudeCliTools.setAutoSyncEnabled(testProjectDir, true);
claudeCliTools.setAutoSyncEnabled(testProjectDir, false);
const retrieved = claudeCliTools.getAutoSyncEnabled(testProjectDir);
assert.equal(retrieved, false);
});
it('should return undefined when not set', () => {
const retrieved = claudeCliTools.getAutoSyncEnabled(testProjectDir);
assert.equal(retrieved, undefined);
});
it('should toggle between true and false', () => {
claudeCliTools.setAutoSyncEnabled(testProjectDir, true);
let retrieved = claudeCliTools.getAutoSyncEnabled(testProjectDir);
assert.equal(retrieved, true);
claudeCliTools.setAutoSyncEnabled(testProjectDir, false);
retrieved = claudeCliTools.getAutoSyncEnabled(testProjectDir);
assert.equal(retrieved, false);
claudeCliTools.setAutoSyncEnabled(testProjectDir, true);
retrieved = claudeCliTools.getAutoSyncEnabled(testProjectDir);
assert.equal(retrieved, true);
});
});
describe('setSmartContextEnabled / getSmartContextEnabled', () => {
it('should set and get smart context enabled status', () => {
const result = claudeCliTools.setSmartContextEnabled(testProjectDir, true);
assert.equal(result.smartContext.enabled, true);
const retrieved = claudeCliTools.getSmartContextEnabled(testProjectDir);
assert.equal(retrieved, true);
});
it('should persist smart context status to file', () => {
claudeCliTools.setSmartContextEnabled(testProjectDir, true);
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
assert.ok(existsSync(settingsPath), 'Settings file should exist');
const content = JSON.parse(readFileSync(settingsPath, 'utf-8'));
assert.equal(content.smartContext.enabled, true);
});
it('should preserve other smartContext properties', () => {
// First, load settings to check default maxFiles
const settings = claudeCliTools.loadClaudeCliSettings(testProjectDir);
const defaultMaxFiles = settings.smartContext.maxFiles;
claudeCliTools.setSmartContextEnabled(testProjectDir, true);
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
const content = JSON.parse(readFileSync(settingsPath, 'utf-8'));
assert.equal(content.smartContext.enabled, true);
assert.equal(content.smartContext.maxFiles, defaultMaxFiles, 'maxFiles should be preserved');
});
it('should return false when not set', () => {
const retrieved = claudeCliTools.getSmartContextEnabled(testProjectDir);
assert.equal(retrieved, false);
});
});
describe('setNativeResume / getNativeResume', () => {
it('should set and get native resume status', () => {
const result = claudeCliTools.setNativeResume(testProjectDir, false);
assert.equal(result.nativeResume, false);
const retrieved = claudeCliTools.getNativeResume(testProjectDir);
assert.equal(retrieved, false);
});
it('should persist native resume status to file', () => {
claudeCliTools.setNativeResume(testProjectDir, false);
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
assert.ok(existsSync(settingsPath), 'Settings file should exist');
const content = JSON.parse(readFileSync(settingsPath, 'utf-8'));
assert.equal(content.nativeResume, false);
});
it('should return true when not set (default)', () => {
const retrieved = claudeCliTools.getNativeResume(testProjectDir);
assert.equal(retrieved, true);
});
});
describe('Multiple settings updates', () => {
it('should handle multiple settings updates in sequence', () => {
claudeCliTools.setPromptFormat(testProjectDir, 'yaml');
claudeCliTools.setDefaultModel(testProjectDir, 'gemini-2.5-pro');
claudeCliTools.setAutoSyncEnabled(testProjectDir, true);
claudeCliTools.setSmartContextEnabled(testProjectDir, true);
claudeCliTools.setNativeResume(testProjectDir, false);
assert.equal(claudeCliTools.getPromptFormat(testProjectDir), 'yaml');
assert.equal(claudeCliTools.getDefaultModel(testProjectDir), 'gemini-2.5-pro');
assert.equal(claudeCliTools.getAutoSyncEnabled(testProjectDir), true);
assert.equal(claudeCliTools.getSmartContextEnabled(testProjectDir), true);
assert.equal(claudeCliTools.getNativeResume(testProjectDir), false);
});
it('should preserve existing settings when updating one', () => {
claudeCliTools.setPromptFormat(testProjectDir, 'json');
claudeCliTools.setDefaultModel(testProjectDir, 'test-model');
// Update only auto-sync
claudeCliTools.setAutoSyncEnabled(testProjectDir, true);
// Verify previous settings are preserved
assert.equal(claudeCliTools.getPromptFormat(testProjectDir), 'json');
assert.equal(claudeCliTools.getDefaultModel(testProjectDir), 'test-model');
assert.equal(claudeCliTools.getAutoSyncEnabled(testProjectDir), true);
});
});
describe('Performance', () => {
it('should complete setter operations in under 10ms', () => {
const operations = [
() => claudeCliTools.setPromptFormat(testProjectDir, 'yaml'),
() => claudeCliTools.setDefaultModel(testProjectDir, 'test-model'),
() => claudeCliTools.setAutoSyncEnabled(testProjectDir, true),
() => claudeCliTools.setSmartContextEnabled(testProjectDir, true),
() => claudeCliTools.setNativeResume(testProjectDir, false),
];
for (const operation of operations) {
const start = Date.now();
operation();
const duration = Date.now() - start;
assert.ok(duration < 10, `Operation should complete in under 10ms (took ${duration}ms)`);
}
});
it('should complete getter operations in under 10ms', () => {
// Set up some data first
claudeCliTools.setPromptFormat(testProjectDir, 'yaml');
claudeCliTools.setDefaultModel(testProjectDir, 'test-model');
claudeCliTools.setAutoSyncEnabled(testProjectDir, true);
const operations = [
() => claudeCliTools.getPromptFormat(testProjectDir),
() => claudeCliTools.getDefaultModel(testProjectDir),
() => claudeCliTools.getAutoSyncEnabled(testProjectDir),
() => claudeCliTools.getSmartContextEnabled(testProjectDir),
() => claudeCliTools.getNativeResume(testProjectDir),
];
for (const operation of operations) {
const start = Date.now();
operation();
const duration = Date.now() - start;
assert.ok(duration < 10, `Operation should complete in under 10ms (took ${duration}ms)`);
}
});
});
describe('File corruption handling', () => {
it('should handle invalid JSON gracefully', () => {
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
const claudeDir = join(TEST_CCW_HOME, '.claude');
// Create .claude directory if it doesn't exist
if (!existsSync(claudeDir)) {
mkdtempSync(claudeDir);
}
// Write invalid JSON
writeFileSync(settingsPath, '{invalid json}', 'utf-8');
// Getters should return defaults
assert.equal(claudeCliTools.getPromptFormat(testProjectDir), 'plain');
assert.equal(claudeCliTools.getDefaultModel(testProjectDir), undefined);
assert.equal(claudeCliTools.getAutoSyncEnabled(testProjectDir), undefined);
});
it('should recover from corrupted file by overwriting', () => {
const settingsPath = join(TEST_CCW_HOME, '.claude', 'cli-settings.json');
const claudeDir = join(TEST_CCW_HOME, '.claude');
// Create .claude directory if it doesn't exist
if (!existsSync(claudeDir)) {
mkdtempSync(claudeDir);
}
// Write invalid JSON
writeFileSync(settingsPath, '{invalid json}', 'utf-8');
// Setter should fix the file
claudeCliTools.setPromptFormat(testProjectDir, 'yaml');
// Should now read correctly
assert.equal(claudeCliTools.getPromptFormat(testProjectDir), 'yaml');
// File should be valid JSON
const content = JSON.parse(readFileSync(settingsPath, 'utf-8'));
assert.equal(content.promptFormat, 'yaml');
});
});
describe('Edge cases', () => {
it('should handle empty string for defaultModel', () => {
claudeCliTools.setDefaultModel(testProjectDir, '');
const retrieved = claudeCliTools.getDefaultModel(testProjectDir);
assert.equal(retrieved, '');
});
it('should handle very long model names', () => {
const longModelName = 'a'.repeat(1000);
claudeCliTools.setDefaultModel(testProjectDir, longModelName);
const retrieved = claudeCliTools.getDefaultModel(testProjectDir);
assert.equal(retrieved, longModelName);
});
it('should handle special characters in model names', () => {
const specialName = 'model-@#$%^&*()_+{}[]|:;<>?,./~`';
claudeCliTools.setDefaultModel(testProjectDir, specialName);
const retrieved = claudeCliTools.getDefaultModel(testProjectDir);
assert.equal(retrieved, specialName);
});
});
});