ocak 0.4.0 → 0.6.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.
- checksums.yaml +4 -4
- data/README.md +101 -21
- data/lib/ocak/agent_generator.rb +11 -1
- data/lib/ocak/batch_processing.rb +132 -0
- data/lib/ocak/claude_runner.rb +12 -8
- data/lib/ocak/cli.rb +13 -0
- data/lib/ocak/command_runner.rb +39 -0
- data/lib/ocak/commands/hiz.rb +28 -28
- data/lib/ocak/commands/init.rb +37 -0
- data/lib/ocak/commands/issue/close.rb +37 -0
- data/lib/ocak/commands/issue/create.rb +59 -0
- data/lib/ocak/commands/issue/edit.rb +31 -0
- data/lib/ocak/commands/issue/list.rb +43 -0
- data/lib/ocak/commands/issue/view.rb +58 -0
- data/lib/ocak/commands/resume.rb +11 -9
- data/lib/ocak/commands/status.rb +29 -12
- data/lib/ocak/config.rb +72 -1
- data/lib/ocak/conflict_resolution.rb +73 -0
- data/lib/ocak/failure_reporting.rb +6 -3
- data/lib/ocak/git_utils.rb +18 -11
- data/lib/ocak/instance_builders.rb +54 -0
- data/lib/ocak/issue_backend.rb +31 -0
- data/lib/ocak/issue_fetcher.rb +9 -0
- data/lib/ocak/issue_state_machine.rb +36 -0
- data/lib/ocak/local_issue_fetcher.rb +165 -0
- data/lib/ocak/local_merge_manager.rb +104 -0
- data/lib/ocak/merge_manager.rb +30 -103
- data/lib/ocak/merge_orchestration.rb +36 -24
- data/lib/ocak/merge_verification.rb +40 -0
- data/lib/ocak/parallel_execution.rb +36 -0
- data/lib/ocak/pipeline_executor.rb +17 -185
- data/lib/ocak/pipeline_runner.rb +32 -180
- data/lib/ocak/planner.rb +16 -1
- data/lib/ocak/project_key.rb +38 -0
- data/lib/ocak/reready_processor.rb +11 -11
- data/lib/ocak/run_report.rb +5 -2
- data/lib/ocak/shutdown_handling.rb +67 -0
- data/lib/ocak/state_management.rb +104 -0
- data/lib/ocak/step_execution.rb +66 -0
- data/lib/ocak/stream_parser.rb +1 -1
- data/lib/ocak/target_resolver.rb +41 -0
- data/lib/ocak/templates/agents/auditor.md.erb +38 -9
- data/lib/ocak/templates/agents/implementer.md.erb +35 -8
- data/lib/ocak/templates/agents/merger.md.erb +24 -5
- data/lib/ocak/templates/agents/pipeline.md.erb +22 -0
- data/lib/ocak/templates/agents/reviewer.md.erb +2 -2
- data/lib/ocak/templates/agents/security_reviewer.md.erb +11 -0
- data/lib/ocak/templates/gitignore_additions.txt +1 -0
- data/lib/ocak/templates/ocak.yml.erb +24 -0
- data/lib/ocak/verification.rb +6 -1
- data/lib/ocak/worktree_manager.rb +9 -6
- data/lib/ocak.rb +1 -1
- metadata +21 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
module Ocak
|
|
6
|
+
module TargetResolver
|
|
7
|
+
# Resolves the target repo for an issue.
|
|
8
|
+
# Returns { name:, path: } hash or nil (single-repo mode).
|
|
9
|
+
# Raises TargetResolutionError on missing/invalid target in multi-repo mode.
|
|
10
|
+
def self.resolve(issue, config:)
|
|
11
|
+
return nil unless config.multi_repo?
|
|
12
|
+
|
|
13
|
+
body = issue['body'].to_s
|
|
14
|
+
repo_name = extract_target_name(body, field: config.target_field)
|
|
15
|
+
|
|
16
|
+
unless repo_name
|
|
17
|
+
raise TargetResolutionError,
|
|
18
|
+
"Issue ##{issue['number']} is missing required '#{config.target_field}' field in body. " \
|
|
19
|
+
"Known repos: #{config.repos.keys.join(', ')}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
config.resolve_repo(repo_name)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Extract target name from YAML front-matter.
|
|
26
|
+
# Returns the target name string, or nil if not found.
|
|
27
|
+
def self.extract_target_name(body, field:)
|
|
28
|
+
match = body.match(/\A---\s*\n(.*?)\n---/m)
|
|
29
|
+
return nil unless match
|
|
30
|
+
|
|
31
|
+
frontmatter = YAML.safe_load(match[1])
|
|
32
|
+
return nil unless frontmatter.is_a?(Hash)
|
|
33
|
+
|
|
34
|
+
frontmatter[field]&.to_s&.strip
|
|
35
|
+
rescue Psych::SyntaxError
|
|
36
|
+
nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class TargetResolutionError < StandardError; end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -18,6 +18,7 @@ You audit changed files as a pre-merge gate. You are read-only. Focus ONLY on fi
|
|
|
18
18
|
git diff main --name-only
|
|
19
19
|
```
|
|
20
20
|
3. Read every changed file in full
|
|
21
|
+
4. Read the corresponding test files for each changed file
|
|
21
22
|
|
|
22
23
|
## Audit Checklist
|
|
23
24
|
|
|
@@ -55,6 +56,7 @@ For each changed file, check:
|
|
|
55
56
|
- Are there tests for the changed code?
|
|
56
57
|
- Do tests cover error paths?
|
|
57
58
|
- Do tests cover edge cases?
|
|
59
|
+
- Do tests assert specific outcomes, not just "doesn't crash"?
|
|
58
60
|
|
|
59
61
|
### Data
|
|
60
62
|
- Potential N+1 queries or unbounded queries
|
|
@@ -66,22 +68,49 @@ For each changed file, check:
|
|
|
66
68
|
```
|
|
67
69
|
## Audit Report
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
[List any critical security or correctness issues. Use the word BLOCK for critical items.]
|
|
71
|
+
**Files audited**: N
|
|
71
72
|
|
|
72
|
-
###
|
|
73
|
-
[Pattern violations, missing tests, minor issues]
|
|
73
|
+
### Findings
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
#### 🔴 Critical — [Title]
|
|
76
|
+
**File**: `path/to/file:42`
|
|
77
|
+
**Category**: [Security | Pattern | Error Handling | Test Coverage | Data]
|
|
78
|
+
**Issue**: [What's wrong]
|
|
79
|
+
**Impact**: [What could go wrong]
|
|
80
|
+
**Recommendation**: [Exact fix]
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
#### 🟡 Warning — [Title]
|
|
83
|
+
**File**: `path/to/file:78`
|
|
84
|
+
**Category**: [category]
|
|
85
|
+
**Issue**: [What's wrong]
|
|
86
|
+
**Recommendation**: [How to fix]
|
|
87
|
+
|
|
88
|
+
#### 🟢 Good — [Title]
|
|
89
|
+
[What was done well]
|
|
90
|
+
|
|
91
|
+
### Test Coverage Summary
|
|
92
|
+
|
|
93
|
+
| Changed File | Test File | Methods Tested | Missing Coverage |
|
|
94
|
+
|-------------|-----------|---------------|-----------------|
|
|
95
|
+
| `path/to/file` | `path/to/file_test` | 4/5 | `edge_case_method` |
|
|
96
|
+
| `path/to/other` | ❌ None | 0/3 | All methods |
|
|
97
|
+
|
|
98
|
+
### Verdict
|
|
99
|
+
|
|
100
|
+
**PASS** — No critical findings. Safe to merge.
|
|
101
|
+
or
|
|
102
|
+
**PASS WITH WARNINGS** — N warnings found. Review recommended but not blocking.
|
|
103
|
+
or
|
|
104
|
+
**BLOCK** — N critical findings. Must fix before merge. [List the critical items]
|
|
80
105
|
```
|
|
81
106
|
|
|
82
|
-
|
|
107
|
+
## Blocking Rules
|
|
108
|
+
|
|
109
|
+
The auditor blocks merge (outputs "BLOCK" verdict) ONLY for:
|
|
83
110
|
- Authentication/authorization bypass
|
|
84
111
|
- Injection vulnerabilities
|
|
85
112
|
- Secrets exposure
|
|
86
113
|
- Data corruption risks
|
|
87
114
|
- Critical missing tests for dangerous operations
|
|
115
|
+
|
|
116
|
+
All other findings are warnings — reported but not blocking.
|
|
@@ -11,10 +11,11 @@ You implement GitHub issues. The issue is your single source of truth — everyt
|
|
|
11
11
|
|
|
12
12
|
## Before You Start
|
|
13
13
|
|
|
14
|
-
1.
|
|
15
|
-
2. Read `
|
|
16
|
-
3. Read
|
|
17
|
-
4.
|
|
14
|
+
1. Check branch state: `git log main..HEAD --oneline` and `git diff main --stat` — work may already be partially done
|
|
15
|
+
2. Read the issue via `gh issue view <number> --json title,body,labels`
|
|
16
|
+
3. Read `CLAUDE.md` for project conventions
|
|
17
|
+
4. Read every file listed in the issue's "Relevant files" and "Patterns to Follow" sections
|
|
18
|
+
5. When writing new code, find the closest existing example first (neighboring file in the same directory/namespace) and mirror its structure exactly
|
|
18
19
|
|
|
19
20
|
## Implementation Rules
|
|
20
21
|
|
|
@@ -97,12 +98,29 @@ You implement GitHub issues. The issue is your single source of truth — everyt
|
|
|
97
98
|
<%- end -%>
|
|
98
99
|
<%- end -%>
|
|
99
100
|
|
|
101
|
+
### Working Directory Context
|
|
102
|
+
If a CLAUDE.md file exists in the current working directory, read it for project-specific conventions, patterns, and architecture. This is especially important when working in a repository you haven't seen before.
|
|
103
|
+
|
|
100
104
|
### General Rules
|
|
101
105
|
|
|
102
106
|
- Do NOT add features, refactoring, or improvements beyond what the issue specifies
|
|
103
107
|
- Do NOT add comments, docstrings, or type annotations to code you didn't write
|
|
104
108
|
- Match the existing code style exactly — look at neighboring files
|
|
105
109
|
|
|
110
|
+
### Scope Discipline (CRITICAL)
|
|
111
|
+
|
|
112
|
+
You MUST NOT modify code outside the issue's scope. This is the #1 source of pipeline regressions. Specifically:
|
|
113
|
+
|
|
114
|
+
- **Do NOT change existing method signatures** unless the issue requires it
|
|
115
|
+
- **Do NOT change error messages or string literals** unless the issue requires it
|
|
116
|
+
- **Do NOT change query logic** (e.g., operators, sort order) unless the issue requires it
|
|
117
|
+
- **Do NOT change data types** unless the issue requires it
|
|
118
|
+
- **Do NOT delete existing tests** — only add new ones or modify tests for code you changed
|
|
119
|
+
- **Do NOT remove security protections** (rate limiting, input validation, access checks)
|
|
120
|
+
- **Do NOT change configuration files** unless the issue requires it
|
|
121
|
+
|
|
122
|
+
Before each commit, run `git diff main --stat` and verify EVERY changed file is justified by the issue's acceptance criteria. If a file appears that shouldn't be there, revert it with `git checkout main -- <file>`.
|
|
123
|
+
|
|
106
124
|
## Testing Requirements
|
|
107
125
|
|
|
108
126
|
Write tests for every acceptance criterion in the issue:
|
|
@@ -153,21 +171,30 @@ Combine related changes: a class and its tests go in one commit, not two.
|
|
|
153
171
|
- If a lint fix is needed for already-committed code, make a separate `style` commit
|
|
154
172
|
- Keep commits small and reviewable — if a commit touches 10+ files across unrelated areas, split it
|
|
155
173
|
|
|
174
|
+
## When Stuck
|
|
175
|
+
|
|
176
|
+
- **Test won't pass after 2 attempts**: Re-read the full source file and the full test file. The answer is usually in existing code you haven't read yet.
|
|
177
|
+
- **Can't find the right pattern**: Look at the nearest neighboring file in the same directory — don't invent a new approach.
|
|
178
|
+
- **Unsure what a method does**: Read the method's test file, not just its source.
|
|
179
|
+
- **Don't iterate on a broken approach**: If your approach fails twice, switch to a different strategy.
|
|
180
|
+
|
|
156
181
|
## Verification Checklist
|
|
157
182
|
|
|
158
183
|
After implementation, run these commands and fix ALL failures before finishing:
|
|
159
184
|
|
|
185
|
+
1. **Scope check**: `git diff main --stat` — verify every file is justified by the issue. Revert any unrelated changes.
|
|
186
|
+
2. **Deleted test check**: `git diff main` — verify you haven't deleted any existing test methods. If you have, restore them.
|
|
160
187
|
<%- if test_command -%>
|
|
161
|
-
|
|
188
|
+
3. **Tests**: `<%= test_command %>`
|
|
162
189
|
<%- end -%>
|
|
163
190
|
<%- if lint_command -%>
|
|
164
|
-
|
|
191
|
+
4. **Lint**: `<%= lint_command %>`
|
|
165
192
|
<%- end -%>
|
|
166
193
|
<%- if format_command -%>
|
|
167
|
-
|
|
194
|
+
5. **Format**: `<%= format_command %>`
|
|
168
195
|
<%- end -%>
|
|
169
196
|
<%- security_commands.each_with_index do |cmd, i| -%>
|
|
170
|
-
<%= i +
|
|
197
|
+
<%= i + 6 %>. **Security**: `<%= cmd %>`
|
|
171
198
|
<%- end -%>
|
|
172
199
|
|
|
173
200
|
Do NOT stop until all commands pass. If a test fails, read the error, fix the code, and re-run. Maximum 5 fix attempts per command — if still failing after 5 attempts, report what's failing and why.
|
|
@@ -13,21 +13,29 @@ You handle the git workflow for completed issues.
|
|
|
13
13
|
|
|
14
14
|
### 1. Verify Readiness
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Tests and linters were already verified by the implementer. Do NOT re-run the full test suite — it wastes time and money.
|
|
17
17
|
|
|
18
|
+
Only re-run tests if you had to resolve merge conflicts or edit files:
|
|
18
19
|
```bash
|
|
19
20
|
<%- if test_command -%>
|
|
20
|
-
#
|
|
21
|
+
# ONLY after resolving merge conflicts:
|
|
21
22
|
<%= test_command %>
|
|
22
23
|
<%- end -%>
|
|
23
|
-
|
|
24
24
|
<%- if lint_command -%>
|
|
25
|
-
# Linter passes
|
|
26
25
|
<%= lint_command %>
|
|
27
26
|
<%- end -%>
|
|
27
|
+
<%- unless test_command || lint_command -%>
|
|
28
|
+
# No specific test/lint commands configured. Detect from project structure:
|
|
29
|
+
# - Gemfile → bundle exec rspec (or bundle exec rake test)
|
|
30
|
+
# - package.json → npm test
|
|
31
|
+
# - Cargo.toml → cargo test
|
|
32
|
+
# - go.mod → go test ./...
|
|
33
|
+
# - pyproject.toml / setup.py → pytest
|
|
34
|
+
# Read the project's CLAUDE.md for additional conventions.
|
|
35
|
+
<%- end -%>
|
|
28
36
|
```
|
|
29
37
|
|
|
30
|
-
If anything fails, STOP and report the failures. Do not create a PR with failing checks.
|
|
38
|
+
If anything fails after conflict resolution, STOP and report the failures. Do not create a PR with failing checks.
|
|
31
39
|
|
|
32
40
|
### 2. Create Pull Request
|
|
33
41
|
|
|
@@ -64,6 +72,9 @@ Closes #<issue-number>
|
|
|
64
72
|
<%- if lint_command -%>
|
|
65
73
|
- `<%= lint_command %>` — passed
|
|
66
74
|
<%- end -%>
|
|
75
|
+
<%- unless test_command || lint_command -%>
|
|
76
|
+
- Stack auto-detected from project structure; commands detected at runtime
|
|
77
|
+
<%- end -%>
|
|
67
78
|
EOF
|
|
68
79
|
)"
|
|
69
80
|
```
|
|
@@ -87,6 +98,13 @@ gh pr merge --merge --delete-branch
|
|
|
87
98
|
gh issue close <number> --comment "Implemented in PR #<pr-number>"
|
|
88
99
|
```
|
|
89
100
|
|
|
101
|
+
### 5. Clean Up
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
git checkout main
|
|
105
|
+
git pull origin main
|
|
106
|
+
```
|
|
107
|
+
|
|
90
108
|
## Output
|
|
91
109
|
|
|
92
110
|
```
|
|
@@ -94,4 +112,5 @@ gh issue close <number> --comment "Implemented in PR #<pr-number>"
|
|
|
94
112
|
- PR: #<number> (<url>)
|
|
95
113
|
- Issue: #<number> closed
|
|
96
114
|
- Branch: <name> (deleted)
|
|
115
|
+
- Merge commit: <sha>
|
|
97
116
|
```
|
|
@@ -33,6 +33,15 @@ gh issue view <number> --json title,body,labels
|
|
|
33
33
|
<%- if test_command -%>
|
|
34
34
|
- `<%= test_command %>`
|
|
35
35
|
<%- end -%>
|
|
36
|
+
<%- unless lint_command || test_command -%>
|
|
37
|
+
- No specific commands configured. Detect from project structure:
|
|
38
|
+
- Gemfile → bundle exec rspec (or bundle exec rake test)
|
|
39
|
+
- package.json → npm test
|
|
40
|
+
- Cargo.toml → cargo test
|
|
41
|
+
- go.mod → go test ./...
|
|
42
|
+
- pyproject.toml / setup.py → pytest
|
|
43
|
+
- Read the project's CLAUDE.md for additional conventions.
|
|
44
|
+
<%- end -%>
|
|
36
45
|
|
|
37
46
|
### Phase 2: Self-Review
|
|
38
47
|
|
|
@@ -43,6 +52,10 @@ git diff main --stat
|
|
|
43
52
|
git diff main
|
|
44
53
|
```
|
|
45
54
|
|
|
55
|
+
**Scope check**: Verify EVERY changed file is justified by the issue's acceptance criteria. If a file appears that shouldn't be there, revert it with `git checkout main -- <file>`.
|
|
56
|
+
|
|
57
|
+
**Deleted test check**: Verify you haven't deleted any existing test methods. If you have, restore them.
|
|
58
|
+
|
|
46
59
|
For each acceptance criterion, verify:
|
|
47
60
|
- Is it implemented correctly?
|
|
48
61
|
- Is it tested?
|
|
@@ -84,6 +97,15 @@ Run the complete check suite one last time:
|
|
|
84
97
|
<%- if test_command -%>
|
|
85
98
|
<%= test_command %>
|
|
86
99
|
<%- end -%>
|
|
100
|
+
<%- unless lint_command || test_command -%>
|
|
101
|
+
# No specific commands configured. Detect from project structure:
|
|
102
|
+
# - Gemfile → bundle exec rspec (or bundle exec rake test)
|
|
103
|
+
# - package.json → npm test
|
|
104
|
+
# - Cargo.toml → cargo test
|
|
105
|
+
# - go.mod → go test ./...
|
|
106
|
+
# - pyproject.toml / setup.py → pytest
|
|
107
|
+
# Read the project's CLAUDE.md for additional conventions.
|
|
108
|
+
<%- end -%>
|
|
87
109
|
```
|
|
88
110
|
|
|
89
111
|
ALL must pass. If anything fails, fix it. Maximum 3 fix cycles — if still failing after 3 attempts, stop and report what's broken.
|
|
@@ -85,8 +85,8 @@ Rate each finding:
|
|
|
85
85
|
[What was done well]
|
|
86
86
|
|
|
87
87
|
### Acceptance Criteria Check
|
|
88
|
-
- [ ] Criterion 1:
|
|
89
|
-
- [ ] Criterion 2:
|
|
88
|
+
- [ ] Criterion 1: ✅ Implemented and tested / ❌ Missing [details]
|
|
89
|
+
- [ ] Criterion 2: ✅ / ❌
|
|
90
90
|
|
|
91
91
|
### Test Coverage
|
|
92
92
|
- [List any untested paths or missing edge cases]
|
|
@@ -10,6 +10,10 @@ model: sonnet
|
|
|
10
10
|
|
|
11
11
|
You perform security-focused code review. You are read-only.
|
|
12
12
|
|
|
13
|
+
## Focus
|
|
14
|
+
|
|
15
|
+
You run AFTER the code reviewer. Focus on security-specific concerns that a general code reviewer would miss. Do NOT repeat general code quality findings (missing tests, naming, patterns). Your value is catching auth bypasses, injection vectors, data exposure, and business logic integrity issues that require security expertise.
|
|
16
|
+
|
|
13
17
|
## Setup
|
|
14
18
|
|
|
15
19
|
1. Read CLAUDE.md for auth architecture and conventions
|
|
@@ -64,6 +68,13 @@ You perform security-focused code review. You are read-only.
|
|
|
64
68
|
- [ ] Logs don't contain PII or secrets
|
|
65
69
|
- [ ] No secrets in code (API keys, passwords, tokens)
|
|
66
70
|
|
|
71
|
+
### Business Logic Integrity
|
|
72
|
+
|
|
73
|
+
- [ ] Domain invariants maintained (e.g., balances sum correctly, state transitions are valid)
|
|
74
|
+
- [ ] Calculations use appropriate precision (no floating-point for monetary/exact values)
|
|
75
|
+
- [ ] Race conditions handled where concurrent access is possible (database locks, transactions)
|
|
76
|
+
- [ ] Multi-tenant data properly scoped — no cross-tenant access paths
|
|
77
|
+
|
|
67
78
|
### Dependencies
|
|
68
79
|
|
|
69
80
|
Run and report results of:
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# WARNING: Commands configured in this file (test_command, lint_command, format_command,
|
|
2
|
+
# setup_command, security_commands) are executed with your user privileges. Treat this
|
|
3
|
+
# file like executable code — review it before running `ocak run` in an unfamiliar repo.
|
|
4
|
+
|
|
1
5
|
# Ocak pipeline configuration
|
|
2
6
|
# Generated by `ocak init` — customize as needed
|
|
3
7
|
|
|
@@ -27,6 +31,17 @@ stack:
|
|
|
27
31
|
<%- end -%>
|
|
28
32
|
<%- end -%>
|
|
29
33
|
|
|
34
|
+
# Multi-repo mode — process issues across multiple local repos
|
|
35
|
+
# Repo path mappings go in ~/.config/ocak/config.yml (machine-specific, not committed)
|
|
36
|
+
# multi_repo: true
|
|
37
|
+
# target_field: target_repo # YAML front-matter field in issue body
|
|
38
|
+
|
|
39
|
+
# Issue backend — 'github' (default) or 'local'
|
|
40
|
+
# Local mode stores issues as files in .ocak/issues/ (no gh CLI needed for issues).
|
|
41
|
+
# Auto-detected: if .ocak/issues/ contains .md files, local mode is used automatically.
|
|
42
|
+
# issues:
|
|
43
|
+
# backend: local
|
|
44
|
+
|
|
30
45
|
# Pipeline settings
|
|
31
46
|
pipeline:
|
|
32
47
|
max_parallel: 5
|
|
@@ -57,29 +72,38 @@ labels:
|
|
|
57
72
|
steps:
|
|
58
73
|
- agent: implementer
|
|
59
74
|
role: implement
|
|
75
|
+
model: sonnet
|
|
60
76
|
- agent: reviewer
|
|
61
77
|
role: review
|
|
78
|
+
model: opus
|
|
62
79
|
- agent: implementer
|
|
63
80
|
role: fix
|
|
64
81
|
condition: has_findings
|
|
82
|
+
model: sonnet
|
|
65
83
|
- agent: reviewer
|
|
66
84
|
role: verify
|
|
67
85
|
condition: had_fixes
|
|
86
|
+
model: opus
|
|
68
87
|
- agent: security_reviewer
|
|
69
88
|
role: security
|
|
89
|
+
model: sonnet
|
|
70
90
|
complexity: full # skipped for simple issues and --fast mode
|
|
71
91
|
- agent: implementer
|
|
72
92
|
role: fix
|
|
73
93
|
condition: has_findings
|
|
74
94
|
complexity: full # skipped for simple issues
|
|
95
|
+
model: sonnet
|
|
75
96
|
- agent: documenter
|
|
76
97
|
role: document
|
|
77
98
|
complexity: full # skipped for simple issues
|
|
99
|
+
model: sonnet
|
|
78
100
|
- agent: auditor
|
|
79
101
|
role: audit
|
|
80
102
|
complexity: full # skipped for simple issues
|
|
103
|
+
model: sonnet
|
|
81
104
|
- agent: merger
|
|
82
105
|
role: merge
|
|
106
|
+
model: sonnet
|
|
83
107
|
|
|
84
108
|
# Agent file paths — override to use custom agents
|
|
85
109
|
agents:
|
data/lib/ocak/verification.rb
CHANGED
|
@@ -52,7 +52,12 @@ module Ocak
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def run_scoped_lint(logger, chdir:)
|
|
55
|
-
changed_stdout, = Open3.capture3('git', 'diff', '--name-only', 'main', chdir: chdir)
|
|
55
|
+
changed_stdout, stderr, status = Open3.capture3('git', 'diff', '--name-only', 'main', chdir: chdir)
|
|
56
|
+
unless status.success?
|
|
57
|
+
logger&.warn("Scoped lint skipped — git diff failed: #{stderr[0..200]}")
|
|
58
|
+
return nil
|
|
59
|
+
end
|
|
60
|
+
|
|
56
61
|
changed_files = changed_stdout.lines.map(&:strip).reject(&:empty?)
|
|
57
62
|
|
|
58
63
|
extensions = lint_extensions_for(@config.language)
|
|
@@ -7,15 +7,18 @@ require 'shellwords'
|
|
|
7
7
|
|
|
8
8
|
module Ocak
|
|
9
9
|
class WorktreeManager
|
|
10
|
-
def initialize(config:, logger: nil)
|
|
10
|
+
def initialize(config:, repo_dir: nil, logger: nil)
|
|
11
11
|
@config = config
|
|
12
12
|
@logger = logger
|
|
13
|
-
@
|
|
13
|
+
@repo_dir = repo_dir || config.project_dir
|
|
14
|
+
@worktree_base = File.join(@repo_dir, config.worktree_dir)
|
|
14
15
|
@mutex = Mutex.new
|
|
15
16
|
end
|
|
16
17
|
|
|
17
|
-
def create(issue_number, setup_command: nil)
|
|
18
|
+
def create(issue_number, setup_command: nil, target_repo: nil)
|
|
18
19
|
@mutex.synchronize do
|
|
20
|
+
raise ArgumentError, "Invalid issue number: #{issue_number}" unless issue_number.to_s.match?(/\A\d+\z/)
|
|
21
|
+
|
|
19
22
|
FileUtils.mkdir_p(@worktree_base)
|
|
20
23
|
|
|
21
24
|
branch = "auto/issue-#{issue_number}-#{SecureRandom.hex(4)}"
|
|
@@ -29,7 +32,7 @@ module Ocak
|
|
|
29
32
|
raise WorktreeError, "Setup command failed: #{stderr}" unless status.success?
|
|
30
33
|
end
|
|
31
34
|
|
|
32
|
-
Worktree.new(path: path, branch: branch, issue_number: issue_number)
|
|
35
|
+
Worktree.new(path: path, branch: branch, issue_number: issue_number, target_repo: target_repo)
|
|
33
36
|
end
|
|
34
37
|
end
|
|
35
38
|
|
|
@@ -66,14 +69,14 @@ module Ocak
|
|
|
66
69
|
removed
|
|
67
70
|
end
|
|
68
71
|
|
|
69
|
-
Worktree = Struct.new(:path, :branch, :issue_number, keyword_init: true) # rubocop:disable Style/RedundantStructKeywordInit
|
|
72
|
+
Worktree = Struct.new(:path, :branch, :issue_number, :target_repo, keyword_init: true) # rubocop:disable Style/RedundantStructKeywordInit
|
|
70
73
|
|
|
71
74
|
class WorktreeError < StandardError; end
|
|
72
75
|
|
|
73
76
|
private
|
|
74
77
|
|
|
75
78
|
def git(*)
|
|
76
|
-
Open3.capture3('git', *, chdir: @
|
|
79
|
+
Open3.capture3('git', *, chdir: @repo_dir)
|
|
77
80
|
end
|
|
78
81
|
|
|
79
82
|
def parse_worktree_list(output)
|
data/lib/ocak.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ocak
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Clay Harmon
|
|
@@ -36,36 +36,56 @@ files:
|
|
|
36
36
|
- bin/ocak
|
|
37
37
|
- lib/ocak.rb
|
|
38
38
|
- lib/ocak/agent_generator.rb
|
|
39
|
+
- lib/ocak/batch_processing.rb
|
|
39
40
|
- lib/ocak/claude_runner.rb
|
|
40
41
|
- lib/ocak/cli.rb
|
|
42
|
+
- lib/ocak/command_runner.rb
|
|
41
43
|
- lib/ocak/commands/audit.rb
|
|
42
44
|
- lib/ocak/commands/clean.rb
|
|
43
45
|
- lib/ocak/commands/debt.rb
|
|
44
46
|
- lib/ocak/commands/design.rb
|
|
45
47
|
- lib/ocak/commands/hiz.rb
|
|
46
48
|
- lib/ocak/commands/init.rb
|
|
49
|
+
- lib/ocak/commands/issue/close.rb
|
|
50
|
+
- lib/ocak/commands/issue/create.rb
|
|
51
|
+
- lib/ocak/commands/issue/edit.rb
|
|
52
|
+
- lib/ocak/commands/issue/list.rb
|
|
53
|
+
- lib/ocak/commands/issue/view.rb
|
|
47
54
|
- lib/ocak/commands/resume.rb
|
|
48
55
|
- lib/ocak/commands/run.rb
|
|
49
56
|
- lib/ocak/commands/status.rb
|
|
50
57
|
- lib/ocak/config.rb
|
|
58
|
+
- lib/ocak/conflict_resolution.rb
|
|
51
59
|
- lib/ocak/failure_reporting.rb
|
|
52
60
|
- lib/ocak/git_utils.rb
|
|
61
|
+
- lib/ocak/instance_builders.rb
|
|
62
|
+
- lib/ocak/issue_backend.rb
|
|
53
63
|
- lib/ocak/issue_fetcher.rb
|
|
64
|
+
- lib/ocak/issue_state_machine.rb
|
|
65
|
+
- lib/ocak/local_issue_fetcher.rb
|
|
66
|
+
- lib/ocak/local_merge_manager.rb
|
|
54
67
|
- lib/ocak/logger.rb
|
|
55
68
|
- lib/ocak/merge_manager.rb
|
|
56
69
|
- lib/ocak/merge_orchestration.rb
|
|
70
|
+
- lib/ocak/merge_verification.rb
|
|
57
71
|
- lib/ocak/monorepo_detector.rb
|
|
72
|
+
- lib/ocak/parallel_execution.rb
|
|
58
73
|
- lib/ocak/pipeline_executor.rb
|
|
59
74
|
- lib/ocak/pipeline_runner.rb
|
|
60
75
|
- lib/ocak/pipeline_state.rb
|
|
61
76
|
- lib/ocak/planner.rb
|
|
62
77
|
- lib/ocak/process_registry.rb
|
|
63
78
|
- lib/ocak/process_runner.rb
|
|
79
|
+
- lib/ocak/project_key.rb
|
|
64
80
|
- lib/ocak/reready_processor.rb
|
|
65
81
|
- lib/ocak/run_report.rb
|
|
82
|
+
- lib/ocak/shutdown_handling.rb
|
|
66
83
|
- lib/ocak/stack_detector.rb
|
|
84
|
+
- lib/ocak/state_management.rb
|
|
67
85
|
- lib/ocak/step_comments.rb
|
|
86
|
+
- lib/ocak/step_execution.rb
|
|
68
87
|
- lib/ocak/stream_parser.rb
|
|
88
|
+
- lib/ocak/target_resolver.rb
|
|
69
89
|
- lib/ocak/templates/agents/auditor.md.erb
|
|
70
90
|
- lib/ocak/templates/agents/documenter.md.erb
|
|
71
91
|
- lib/ocak/templates/agents/implementer.md.erb
|