mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
feat: update execution commands to commit once per solution and enhance reranker model handling
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: execute
|
||||
description: Execute queue with codex using DAG-based parallel orchestration (solution-level)
|
||||
description: Execute queue with DAG-based parallel orchestration (one commit per solution)
|
||||
argument-hint: "[--worktree] [--queue <queue-id>]"
|
||||
allowed-tools: TodoWrite(*), Bash(*), Read(*), AskUserQuestion(*)
|
||||
---
|
||||
@@ -49,7 +49,8 @@ Phase 2: Dispatch Parallel Batch (DAG-driven)
|
||||
│ ├─ Executor calls: ccw issue detail <id> (READ-ONLY)
|
||||
│ ├─ Executor gets FULL SOLUTION with all tasks
|
||||
│ ├─ Executor implements all tasks sequentially (T1 → T2 → T3)
|
||||
│ ├─ Executor tests + commits per task
|
||||
│ ├─ Executor tests + verifies each task
|
||||
│ ├─ Executor commits ONCE per solution (with formatted summary)
|
||||
│ ├─ Executor calls: ccw issue done <id>
|
||||
│ └─ (if worktree) Cleanup: merge branch, remove worktree
|
||||
└─ Wait for batch completion
|
||||
@@ -205,7 +206,7 @@ cd "\${WORKTREE_PATH}"
|
||||
` : '';
|
||||
|
||||
const worktreeCleanup = useWorktree ? `
|
||||
### Step 4: Worktree Completion (User Choice)
|
||||
### Step 5: Worktree Completion (User Choice)
|
||||
|
||||
After all tasks complete, prompt for merge strategy:
|
||||
|
||||
@@ -282,12 +283,34 @@ For each task:
|
||||
1. Follow task.implementation steps
|
||||
2. Run task.test commands
|
||||
3. Verify task.acceptance criteria
|
||||
4. Commit using task.commit specification
|
||||
(Do NOT commit after each task)
|
||||
|
||||
### Step 3: Report Completion
|
||||
When ALL tasks in solution are done:
|
||||
### Step 3: Commit Solution (Once)
|
||||
After ALL tasks pass, commit once with formatted summary:
|
||||
\`\`\`bash
|
||||
ccw issue done ${solutionId} --result '{"summary": "...", "files_modified": [...], "tasks_completed": N}'
|
||||
git add <all-modified-files>
|
||||
git commit -m "[type](scope): [solution.description]
|
||||
|
||||
## Solution Summary
|
||||
- Solution-ID: ${solutionId}
|
||||
- Tasks: T1, T2, ...
|
||||
|
||||
## Tasks Completed
|
||||
- [T1] task1.title: action
|
||||
- [T2] task2.title: action
|
||||
|
||||
## Files Modified
|
||||
- file1.ts
|
||||
- file2.ts
|
||||
|
||||
## Verification
|
||||
- All tests passed
|
||||
- All acceptance criteria verified"
|
||||
\`\`\`
|
||||
|
||||
### Step 4: Report Completion
|
||||
\`\`\`bash
|
||||
ccw issue done ${solutionId} --result '{"summary": "...", "files_modified": [...], "commit": {"hash": "...", "type": "feat"}, "tasks_completed": N}'
|
||||
\`\`\`
|
||||
|
||||
If any task failed:
|
||||
@@ -350,6 +373,7 @@ if (refreshedDag.ready_count > 0) {
|
||||
│ │ detail S-1 │ │ detail S-2 │ │
|
||||
│ │ → gets full solution │ │ → gets full solution │ │
|
||||
│ │ [T1→T2→T3 sequential]│ │ [T1→T2 sequential] │ │
|
||||
│ │ commit (1x solution) │ │ commit (1x solution) │ │
|
||||
│ │ done S-1 │ │ done S-2 │ │
|
||||
│ └──────────────────────┘ └──────────────────────┘ │
|
||||
│ │
|
||||
@@ -361,6 +385,7 @@ if (refreshedDag.ready_count > 0) {
|
||||
**Why this works for parallel:**
|
||||
- `detail <id>` is READ-ONLY → no race conditions
|
||||
- Each executor handles **all tasks within a solution** sequentially
|
||||
- **One commit per solution** with formatted summary (not per-task)
|
||||
- `done <id>` updates only its own solution status
|
||||
- `queue dag` recalculates ready solutions after each batch
|
||||
- Solutions in same batch have NO file conflicts
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Execute all solutions from issue queue with git commit after each task
|
||||
description: Execute all solutions from issue queue with git commit after each solution
|
||||
argument-hint: "[--worktree] [--queue <queue-id>]"
|
||||
---
|
||||
|
||||
@@ -7,7 +7,7 @@ argument-hint: "[--worktree] [--queue <queue-id>]"
|
||||
|
||||
## Core Principle
|
||||
|
||||
**Serial Execution**: Execute solutions ONE BY ONE from the issue queue via `ccw issue next`. For each solution, complete all tasks sequentially (implement → test → commit per task). Continue autonomously until queue is empty.
|
||||
**Serial Execution**: Execute solutions ONE BY ONE from the issue queue via `ccw issue next`. For each solution, complete all tasks sequentially (implement → test → verify), then commit once per solution with formatted summary. Continue autonomously until queue is empty.
|
||||
|
||||
## Worktree Mode (Recommended for Parallel Execution)
|
||||
|
||||
@@ -150,9 +150,9 @@ WHILE solution exists:
|
||||
- IMPLEMENT: Follow task.implementation steps
|
||||
- TEST: Run task.test commands
|
||||
- VERIFY: Check task.acceptance criteria
|
||||
- COMMIT: Stage files, commit with task.commit.message_template
|
||||
3. Report completion via ccw issue done <item_id>
|
||||
4. Fetch next solution via ccw issue next
|
||||
3. COMMIT: Stage all files, commit once with formatted summary
|
||||
4. Report completion via ccw issue done <item_id>
|
||||
5. Fetch next solution via ccw issue next
|
||||
|
||||
WHEN queue empty:
|
||||
Output final summary
|
||||
@@ -275,9 +275,9 @@ update_plan({
|
||||
})
|
||||
```
|
||||
|
||||
**After completing each task** (commit done), mark it as completed:
|
||||
**After completing each task** (verification passed), mark it as completed:
|
||||
```javascript
|
||||
// Mark task as completed
|
||||
// Mark task as completed (commit happens at solution level)
|
||||
update_plan({
|
||||
explanation: `Completed ${task.id}: ${task.title}`,
|
||||
plan: tasks.map(t => ({
|
||||
@@ -360,41 +360,76 @@ All criteria met: YES
|
||||
|
||||
**If any criterion fails**: Go back to IMPLEMENT phase and fix.
|
||||
|
||||
### Phase D: COMMIT
|
||||
|
||||
After all phases pass, commit the changes for this task:
|
||||
|
||||
```bash
|
||||
# Stage all modified files
|
||||
git add path/to/file1.ts path/to/file2.ts ...
|
||||
|
||||
# Commit with task message template
|
||||
git commit -m "$(cat <<'EOF'
|
||||
[task.commit.message_template]
|
||||
|
||||
Solution-ID: [solution_id]
|
||||
Issue-ID: [issue_id]
|
||||
Task-ID: [task.id]
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
**Output format:**
|
||||
```
|
||||
## Committed: [task.title]
|
||||
|
||||
**Commit**: [commit hash]
|
||||
**Message**: [commit message]
|
||||
**Files**: N files changed
|
||||
```
|
||||
|
||||
### Repeat for Next Task
|
||||
|
||||
Continue to next task in `solution.tasks` array until all tasks are complete.
|
||||
|
||||
**Note**: Do NOT commit after each task. Commits happen at solution level after all tasks pass.
|
||||
|
||||
## Step 3.5: Commit Solution
|
||||
|
||||
After ALL tasks in the solution pass implementation, testing, and verification, commit once for the entire solution:
|
||||
|
||||
```bash
|
||||
# Stage all modified files from all tasks
|
||||
git add path/to/file1.ts path/to/file2.ts ...
|
||||
|
||||
# Commit with formatted solution summary
|
||||
git commit -m "$(cat <<'EOF'
|
||||
[commit_type](scope): [solution.description - brief]
|
||||
|
||||
## Solution Summary
|
||||
- **Solution-ID**: [solution_id]
|
||||
- **Issue-ID**: [issue_id]
|
||||
- **Risk/Impact/Complexity**: [solution.analysis.risk]/[solution.analysis.impact]/[solution.analysis.complexity]
|
||||
|
||||
## Tasks Completed
|
||||
- [T1] [task1.title]: [task1.action] [task1.scope]
|
||||
- [T2] [task2.title]: [task2.action] [task2.scope]
|
||||
- ...
|
||||
|
||||
## Files Modified
|
||||
- path/to/file1.ts
|
||||
- path/to/file2.ts
|
||||
- ...
|
||||
|
||||
## Verification
|
||||
- All unit tests passed
|
||||
- All acceptance criteria verified
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
**Commit Type Selection**:
|
||||
- `feat`: New feature or capability
|
||||
- `fix`: Bug fix
|
||||
- `refactor`: Code restructuring without behavior change
|
||||
- `test`: Adding or updating tests
|
||||
- `docs`: Documentation changes
|
||||
- `chore`: Maintenance tasks
|
||||
|
||||
**Output format:**
|
||||
```
|
||||
## Solution Committed: [solution_id]
|
||||
|
||||
**Commit**: [commit hash]
|
||||
**Type**: [commit_type]
|
||||
**Scope**: [scope]
|
||||
|
||||
**Summary**:
|
||||
[solution.description]
|
||||
|
||||
**Tasks**: [N] tasks completed
|
||||
- [x] T1: [task1.title]
|
||||
- [x] T2: [task2.title]
|
||||
...
|
||||
|
||||
**Files**: [M] files changed
|
||||
```
|
||||
|
||||
## Step 4: Report Completion
|
||||
|
||||
After ALL tasks in the solution are complete, report to queue system:
|
||||
After ALL tasks in the solution are complete and committed, report to queue system:
|
||||
|
||||
```javascript
|
||||
// ccw auto-detects worktree and uses main repo's .workflow/
|
||||
@@ -402,7 +437,7 @@ shell_command({
|
||||
command: `ccw issue done ${item_id} --result '${JSON.stringify({
|
||||
files_modified: ["path1", "path2"],
|
||||
tests_passed: true,
|
||||
commits: [{ task_id: "T1", hash: "abc123" }],
|
||||
commit: { hash: "abc123", type: "feat", tasks: ["T1", "T2"] },
|
||||
summary: "[What was accomplished]"
|
||||
})}'`
|
||||
})
|
||||
@@ -427,7 +462,9 @@ const result = shell_command({ command: "ccw issue next" })
|
||||
|
||||
**Output progress:**
|
||||
```
|
||||
✓ [N/M] Completed: [item_id] - [solution.approach]
|
||||
✓ [N/M] Completed: [item_id] - [solution.description]
|
||||
Commit: [commit_hash] ([commit_type])
|
||||
Tasks: [task_count] completed
|
||||
→ Fetching next solution...
|
||||
```
|
||||
|
||||
@@ -444,13 +481,14 @@ When `ccw issue next` returns `{ "status": "empty" }`:
|
||||
|
||||
**Total Solutions Executed**: N
|
||||
**Total Tasks Executed**: M
|
||||
**Total Commits**: N (one per solution)
|
||||
|
||||
**All Commits**:
|
||||
| # | Solution | Task | Commit |
|
||||
|---|----------|------|--------|
|
||||
| 1 | S-1 | T1 | abc123 |
|
||||
| 2 | S-1 | T2 | def456 |
|
||||
| 3 | S-2 | T1 | ghi789 |
|
||||
**Solution Commits**:
|
||||
| # | Solution | Tasks | Commit | Type |
|
||||
|---|----------|-------|--------|------|
|
||||
| 1 | SOL-xxx-1 | T1, T2 | abc123 | feat |
|
||||
| 2 | SOL-xxx-2 | T1 | def456 | fix |
|
||||
| 3 | SOL-yyy-1 | T1, T2, T3 | ghi789 | refactor |
|
||||
|
||||
**Files Modified**:
|
||||
- path/to/file1.ts
|
||||
@@ -463,11 +501,11 @@ When `ccw issue next` returns `{ "status": "empty" }`:
|
||||
## Execution Rules
|
||||
|
||||
1. **Never stop mid-queue** - Continue until queue is empty
|
||||
2. **One solution at a time** - Fully complete (all tasks + report) before moving on
|
||||
3. **Sequential within solution** - Complete each task (including commit) before next
|
||||
4. **Tests MUST pass** - Do not proceed to commit if tests fail
|
||||
5. **Commit after each task** - Each task gets its own commit
|
||||
6. **Self-verify** - All acceptance criteria must pass before commit
|
||||
2. **One solution at a time** - Fully complete (all tasks + commit + report) before moving on
|
||||
3. **Sequential within solution** - Complete each task's implement/test/verify before next task
|
||||
4. **Tests MUST pass** - Do not proceed if any task's tests fail
|
||||
5. **One commit per solution** - All tasks share a single commit with formatted summary
|
||||
6. **Self-verify** - All acceptance criteria must pass before solution commit
|
||||
7. **Report accurately** - Use `ccw issue done` after each solution
|
||||
8. **Handle failures gracefully** - If a solution fails, report via `ccw issue done --fail` and continue to next
|
||||
9. **Track with update_plan** - Use update_plan tool for task progress tracking
|
||||
@@ -480,9 +518,9 @@ When `ccw issue next` returns `{ "status": "empty" }`:
|
||||
| `ccw issue next` returns empty | All done - output final summary |
|
||||
| Tests fail | Fix code, re-run tests |
|
||||
| Verification fails | Go back to implement phase |
|
||||
| Git commit fails | Check staging, retry commit |
|
||||
| Solution commit fails | Check staging, retry commit |
|
||||
| `ccw issue done` fails | Log error, continue to next solution |
|
||||
| Unrecoverable error | Call `ccw issue done --fail`, continue to next |
|
||||
| Any task unrecoverable | Call `ccw issue done --fail`, continue to next solution |
|
||||
|
||||
## CLI Command Reference
|
||||
|
||||
|
||||
@@ -1181,10 +1181,10 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
|
||||
try {
|
||||
const venvStatus = await checkVenvStatus();
|
||||
|
||||
// Default reranker config
|
||||
// Default reranker config (matches fastembed default)
|
||||
const rerankerConfig = {
|
||||
backend: 'onnx',
|
||||
model_name: 'cross-encoder/ms-marco-MiniLM-L-6-v2',
|
||||
backend: 'fastembed',
|
||||
model_name: 'Xenova/ms-marco-MiniLM-L-6-v2',
|
||||
api_provider: 'siliconflow',
|
||||
api_key_set: false,
|
||||
available_backends: ['onnx', 'api', 'litellm', 'legacy'],
|
||||
|
||||
@@ -1076,7 +1076,8 @@ function renderProviderList() {
|
||||
var container = document.getElementById('provider-list');
|
||||
if (!container) return;
|
||||
|
||||
var providers = apiSettingsData.providers || [];
|
||||
// Guard against null apiSettingsData
|
||||
var providers = (apiSettingsData && apiSettingsData.providers) ? apiSettingsData.providers : [];
|
||||
var query = providerSearchQuery.toLowerCase();
|
||||
|
||||
// Filter providers
|
||||
@@ -1147,6 +1148,12 @@ function renderProviderDetail(providerId) {
|
||||
var container = document.getElementById('provider-detail-panel');
|
||||
if (!container) return;
|
||||
|
||||
// Guard against null apiSettingsData
|
||||
if (!apiSettingsData || !apiSettingsData.providers) {
|
||||
renderProviderEmptyState();
|
||||
return;
|
||||
}
|
||||
|
||||
var provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
|
||||
if (!provider) {
|
||||
renderProviderEmptyState();
|
||||
@@ -1370,6 +1377,9 @@ function toggleModelGroup(series) {
|
||||
expandedModelGroups.add(series);
|
||||
}
|
||||
|
||||
// Guard against null apiSettingsData
|
||||
if (!apiSettingsData || !apiSettingsData.providers) return;
|
||||
|
||||
var provider = apiSettingsData.providers.find(function(p) { return p.id === selectedProviderId; });
|
||||
if (provider) {
|
||||
renderModelTree(provider);
|
||||
@@ -1379,10 +1389,20 @@ function toggleModelGroup(series) {
|
||||
/**
|
||||
* Switch model tab (LLM / Embedding)
|
||||
*/
|
||||
function switchModelTab(tab) {
|
||||
async function switchModelTab(tab) {
|
||||
activeModelTab = tab;
|
||||
expandedModelGroups.clear();
|
||||
|
||||
// Guard against null apiSettingsData or providers - try to load if not available
|
||||
if (!apiSettingsData || !apiSettingsData.providers) {
|
||||
console.warn('[API Settings] switchModelTab: loading data first...');
|
||||
await loadApiSettings(true);
|
||||
if (!apiSettingsData || !apiSettingsData.providers) {
|
||||
console.error('[API Settings] Failed to load API settings data');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var provider = apiSettingsData.providers.find(function(p) { return p.id === selectedProviderId; });
|
||||
if (provider) {
|
||||
renderProviderDetail(selectedProviderId);
|
||||
|
||||
@@ -1693,9 +1693,14 @@ async function loadRerankerModelList() {
|
||||
try {
|
||||
// Get current reranker config
|
||||
var response = await fetch('/api/codexlens/reranker/config');
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to load reranker config: ' + response.status);
|
||||
}
|
||||
var config = await response.json();
|
||||
var currentModel = config.model_name || 'Xenova/ms-marco-MiniLM-L-6-v2';
|
||||
var currentBackend = config.backend || 'fastembed';
|
||||
|
||||
// Handle API response format
|
||||
var currentModel = config.model_name || config.result?.reranker_model || 'Xenova/ms-marco-MiniLM-L-6-v2';
|
||||
var currentBackend = config.backend || config.result?.reranker_backend || 'fastembed';
|
||||
|
||||
var html = '<div class="space-y-2">';
|
||||
|
||||
@@ -1713,8 +1718,19 @@ async function loadRerankerModelList() {
|
||||
|
||||
// Show models for local backend only
|
||||
if (currentBackend === 'fastembed' || currentBackend === 'onnx') {
|
||||
// Helper to match model names (handles different prefixes like Xenova/ vs cross-encoder/)
|
||||
function modelMatches(current, target) {
|
||||
if (!current || !target) return false;
|
||||
// Exact match
|
||||
if (current === target) return true;
|
||||
// Match by base name (after last /)
|
||||
var currentBase = current.split('/').pop();
|
||||
var targetBase = target.split('/').pop();
|
||||
return currentBase === targetBase;
|
||||
}
|
||||
|
||||
RERANKER_MODELS.forEach(function(model) {
|
||||
var isActive = currentModel === model.name;
|
||||
var isActive = modelMatches(currentModel, model.name);
|
||||
var statusIcon = isActive
|
||||
? '<i data-lucide="check-circle" class="w-3.5 h-3.5 text-success"></i>'
|
||||
: '<i data-lucide="circle" class="w-3.5 h-3.5 text-muted"></i>';
|
||||
@@ -1870,7 +1886,12 @@ async function loadGpuDevicesForModeSelector() {
|
||||
if (!gpuSelect) return;
|
||||
|
||||
try {
|
||||
var response = await fetch('/api/codexlens/gpu/devices');
|
||||
var response = await fetch('/api/codexlens/gpu/list');
|
||||
if (!response.ok) {
|
||||
console.warn('[CodexLens] GPU list endpoint returned:', response.status);
|
||||
gpuSelect.innerHTML = '<option value="auto">Auto</option>';
|
||||
return;
|
||||
}
|
||||
var result = await response.json();
|
||||
|
||||
var html = '<option value="auto">Auto</option>';
|
||||
@@ -3785,19 +3806,12 @@ async function checkIndexHealth() {
|
||||
|
||||
var lastIndexTime = currentIndex.lastModified ? new Date(currentIndex.lastModified) : null;
|
||||
|
||||
// Get git commits since last index
|
||||
// Estimate staleness based on time (git API not available)
|
||||
var commitsSince = 0;
|
||||
try {
|
||||
var gitResponse = await fetch('/api/git/commits-since?since=' + encodeURIComponent(currentIndex.lastModified || ''));
|
||||
var gitData = await gitResponse.json();
|
||||
commitsSince = gitData.count || 0;
|
||||
} catch (gitErr) {
|
||||
console.warn('[CodexLens] Could not get git history:', gitErr);
|
||||
// Fallback: estimate based on time
|
||||
if (lastIndexTime) {
|
||||
var hoursSince = (Date.now() - lastIndexTime.getTime()) / (1000 * 60 * 60);
|
||||
commitsSince = Math.floor(hoursSince / 2); // Rough estimate
|
||||
}
|
||||
if (lastIndexTime) {
|
||||
var hoursSince = (Date.now() - lastIndexTime.getTime()) / (1000 * 60 * 60);
|
||||
// Rough estimate: assume ~2 commits per hour on active projects
|
||||
commitsSince = Math.floor(hoursSince / 2);
|
||||
}
|
||||
|
||||
// Determine health status
|
||||
|
||||
Reference in New Issue
Block a user