/ project / planning / claude-ci-serverside-plan.cspec
claude-ci-serverside-plan.cspec
  1  # Claude CI Serverside Implementation Plan
  2  # purpose: Step-by-step implementation guide for Claude worker
  3  # status: verified
  4  # updated: 2026-01-06
  5  # verified: 2026-01-06
  6  # spec_ref: project/descriptive-docs/machine/Claude-CI-Serverside.cspec
  7  
  8  # === VERIFIED SERVER STATE ===
  9  server_state:
 10    host: ci.ac-dc.network
 11    ssh_port: 2584
 12    user: devops
 13  
 14    installed:
 15      python: {path: /usr/bin/python3, version: "3.12.3"}
 16      claude_cli: {path: /usr/bin/claude, version: "2.0.76"}
 17      node: {path: /usr/bin/node, version: "24.12.0"}
 18      npm: {path: /usr/bin/npm, version: "11.6.2"}
 19  
 20    python_packages:
 21      - {name: requests, version: "2.31.0", status: installed}
 22      - {name: anthropic, version: "0.75.0", status: installed}
 23  
 24    directories:
 25      writable: /opt/ci/  # owned by devops
 26      not_writable: /var/lib/  # needs sudo
 27  
 28    credentials:
 29      claude: NOT_CONFIGURED  # need to run: claude /login
 30      forgejo_token: AVAILABLE  # token works, needs to be stored
 31  
 32    api_verified:
 33      endpoint: https://source.ac-dc.network/api/v1
 34      repos_in_org: 12
 35      test_result: success
 36  
 37  # === IMPLEMENTATION PHASES ===
 38  
 39  phases:
 40    total: 4
 41    order: [setup, service, deploy, protect]
 42  
 43  # ============================================================
 44  # PHASE 1: SETUP
 45  # ============================================================
 46  phase_1_setup:
 47    name: Environment Setup
 48  
 49    tasks:
 50      1_1_create_labels:
 51        action: Create labels in Forgejo via API
 52        endpoint: POST /api/v1/orgs/alpha-delta-network/labels
 53        labels:
 54          - name: claude-approved
 55            color: "00ff00"
 56            description: "Claude review passed"
 57          - name: claude-changes-requested
 58            color: "ff0000"
 59            description: "Claude requested changes"
 60        verify: GET /api/v1/orgs/alpha-delta-network/labels
 61  
 62      1_2_setup_credentials:
 63        action: Setup Claude CLI credentials on CI server
 64        host: ci.ac-dc.network
 65        user: devops
 66        commands:
 67          - ssh -p 2584 devops@ci.ac-dc.network
 68          - claude /login
 69          - verify: ls -la ~/.claude/.credentials.json
 70        output: /home/devops/.claude/.credentials.json exists
 71  
 72      1_3_verify_forgejo_token:
 73        action: Verify FORGEJO_TOKEN works
 74        test: |
 75          curl -s -H "Authorization: token $FORGEJO_TOKEN" \
 76            https://source.ac-dc.network/api/v1/user
 77        expect: returns authenticated user info
 78  
 79  # ============================================================
 80  # PHASE 2: SERVICE IMPLEMENTATION
 81  # ============================================================
 82  phase_2_service:
 83    name: Review Service Script
 84    output: tools/claude-review-service.py
 85  
 86    tasks:
 87      2_1_create_script:
 88        action: Create main service script
 89        path: tools/claude-review-service.py
 90  
 91        imports:
 92          - requests
 93          - subprocess
 94          - json
 95          - os
 96          - logging
 97  
 98        classes:
 99          ForgejoClient:
100            methods:
101              - __init__(base_url, token)
102              - list_org_repos(org) -> list[dict]
103              - list_open_prs(owner, repo) -> list[dict]
104              - get_pr_diff(owner, repo, pr_num) -> str
105              - get_pr_details(owner, repo, pr_num) -> dict
106              - get_commit_status(owner, repo, sha) -> dict
107              - post_comment(owner, repo, issue_num, body)
108              - add_label(owner, repo, issue_num, label)
109              - remove_label(owner, repo, issue_num, label)
110              - set_commit_status(owner, repo, sha, state, context, description)
111  
112          ClaudeReviewer:
113            methods:
114              - __init__(credentials_path)
115              - review_diff(diff, pr_info) -> ReviewResult
116  
117            review_prompt: |
118              Review this PR diff for:
119              1. Code quality issues
120              2. Security vulnerabilities
121              3. Architecture concerns
122              4. Missing documentation
123              5. Test coverage gaps
124  
125              Classify each issue as: critical, high, medium, low
126  
127              Return JSON: {approved, summary, issues[], suggestions[]}
128  
129          ReviewService:
130            methods:
131              - __init__(forgejo_client, claude_reviewer)
132              - get_reviewed_shas() -> set  # from state file
133              - save_reviewed_sha(sha)
134              - needs_review(pr) -> bool
135              - should_block(issues) -> bool
136              - format_comment(result) -> str
137              - process_pr(owner, repo, pr)
138              - run()
139  
140        main_logic: |
141          1. Load config from env vars
142          2. Init ForgejoClient and ClaudeReviewer
143          3. For each repo in org:
144             a. List open PRs
145             b. For each PR:
146                - Check if CI passed
147                - Check if already reviewed (by SHA)
148                - If needs review: fetch diff, run Claude, post result
149          4. Log summary
150  
151      2_2_blocking_logic:
152        action: Implement blocking decision
153        code: |
154          def should_block(self, issues: list) -> bool:
155              blocking = {'critical', 'high', 'medium'}
156              return any(i['severity'] in blocking for i in issues)
157  
158      2_3_comment_format:
159        action: Define comment template
160        template: |
161          ## Claude Code Review
162  
163          {%if approved%}
164          ### Approved
165          {summary}
166          {%else%}
167          ### Changes Requested
168          {summary}
169  
170          #### Issues Found
171          {%for issue in issues%}
172          - **[{issue.severity}]** `{issue.file}:{issue.line}` - {issue.message}
173          {%endfor%}
174          {%endif%}
175  
176          {%if suggestions%}
177          #### Suggestions
178          {%for s in suggestions%}
179          - {s}
180          {%endfor%}
181          {%endif%}
182  
183          ---
184          *Automated review by Claude*
185  
186      2_4_state_tracking:
187        action: Track reviewed PRs by SHA
188        path: /opt/ci/claude-review/state/reviewed_shas.json
189        format: |
190          {
191            "owner/repo#pr": {
192              "sha": "abc123",
193              "reviewed_at": "2026-01-06T12:00:00Z",
194              "result": "approved|changes_requested"
195            }
196          }
197  
198  # ============================================================
199  # PHASE 3: DEPLOYMENT
200  # ============================================================
201  phase_3_deploy:
202    name: Deploy to CI Server
203    host: ci.ac-dc.network
204  
205    tasks:
206      3_1_create_directories:
207        action: Create service directories
208        commands:
209          - ssh -p 2584 devops@ci.ac-dc.network "mkdir -p /opt/ci/claude-review"
210          - ssh -p 2584 devops@ci.ac-dc.network "mkdir -p /opt/ci/claude-review/state"
211        note: Using /opt/ci/ which is writable by devops (verified)
212  
213      3_2_copy_script:
214        action: Deploy script to server
215        commands:
216          - scp -P 2584 tools/claude-review-service.py devops@ci.ac-dc.network:/opt/ci/claude-review/
217          - ssh -p 2584 devops@ci.ac-dc.network "chmod +x /opt/ci/claude-review/claude-review-service.py"
218  
219      3_3_create_systemd_service:
220        action: Create systemd service unit
221        path: /etc/systemd/system/claude-review.service
222        note: Requires sudo to write to /etc/systemd/system/
223        content: |
224          [Unit]
225          Description=Claude PR Review Service
226          After=network.target
227  
228          [Service]
229          Type=oneshot
230          User=devops
231          WorkingDirectory=/opt/ci/claude-review
232          ExecStart=/usr/bin/python3 /opt/ci/claude-review/claude-review-service.py
233          Environment=FORGEJO_URL=https://source.ac-dc.network
234          Environment=FORGEJO_TOKEN=2f14498863920f9853e56e554a817654a5ddc917
235          Environment=ORG_NAME=alpha-delta-network
236          Environment=STATE_FILE=/opt/ci/claude-review/state/reviewed_shas.json
237  
238          [Install]
239          WantedBy=multi-user.target
240  
241      3_4_create_systemd_timer:
242        action: Create systemd timer unit
243        path: /etc/systemd/system/claude-review.timer
244        content: |
245          [Unit]
246          Description=Run Claude PR Review every 5 minutes
247  
248          [Timer]
249          OnBootSec=2min
250          OnUnitActiveSec=5min
251  
252          [Install]
253          WantedBy=timers.target
254  
255      3_5_enable_timer:
256        action: Enable and start timer
257        commands:
258          - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl daemon-reload"
259          - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl enable claude-review.timer"
260          - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl start claude-review.timer"
261        verify: systemctl status claude-review.timer
262  
263  # ============================================================
264  # PHASE 4: BRANCH PROTECTION
265  # ============================================================
266  phase_4_protect:
267    name: Configure Branch Protection
268    note: Manual in Forgejo UI for each repo
269  
270    tasks:
271      4_1_protection_rules:
272        action: Set branch protection on main
273        location: Forgejo UI > Repo Settings > Branches > main
274        settings:
275          - enable_push_protection: true
276          - require_status_checks: true
277          - required_checks: [claude-review]
278          - require_approvals: 1
279          - dismiss_stale_reviews: true
280  
281      4_2_alternative_label_gate:
282        action: Alternative - require label for merge
283        note: If status checks not flexible enough
284        rule: Require "claude-approved" label before merge allowed
285  
286  # ============================================================
287  # VERIFICATION
288  # ============================================================
289  verification:
290    test_cases:
291      - name: Service runs without error
292        command: sudo systemctl start claude-review.service
293        expect: exit 0, no errors in journal
294  
295      - name: Timer is active
296        command: systemctl is-active claude-review.timer
297        expect: active
298  
299      - name: Test PR gets reviewed
300        steps:
301          - Create test PR with minor issue
302          - Wait 5 minutes or trigger manually
303          - Verify comment posted
304          - Verify label applied
305  
306      - name: Approved PR can merge
307        steps:
308          - Create clean test PR
309          - Wait for Claude approval
310          - Verify admin can merge
311  
312  # ============================================================
313  # ROLLBACK
314  # ============================================================
315  rollback:
316    steps:
317      - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl stop claude-review.timer"
318      - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl disable claude-review.timer"
319      - Remove branch protection rules in Forgejo UI
320    note: Labels and comments remain but have no effect
321  
322  # ============================================================
323  # FILES CREATED
324  # ============================================================
325  files_created:
326    local:
327      - tools/claude-review-service.py
328  
329    server:
330      - /opt/ci/claude-review/claude-review-service.py
331      - /opt/ci/claude-review/state/reviewed_shas.json
332      - /etc/systemd/system/claude-review.service  # requires sudo
333      - /etc/systemd/system/claude-review.timer    # requires sudo
334  
335  # ============================================================
336  # PREREQUISITES SUMMARY
337  # ============================================================
338  prerequisites:
339    already_done:
340      - Python 3.12.3 installed
341      - requests package installed
342      - anthropic package installed
343      - Claude CLI installed at /usr/bin/claude
344      - /opt/ci/ directory exists and writable
345      - Forgejo API accessible with token
346  
347    still_needed:
348      - Claude credentials: run "claude /login" as devops
349      - Create org labels: claude-approved, claude-changes-requested
350      - Branch protection rules in Forgejo UI