@cxi-lmai/ci-agent-platform 3.0.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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/bin/init.mjs +236 -0
  4. package/package.json +47 -0
  5. package/payload/INSTALL.md +113 -0
  6. package/payload/agents/agent-architect.md +101 -0
  7. package/payload/agents/code-reviewer.md +87 -0
  8. package/payload/agents/codebase-auditor.md +73 -0
  9. package/payload/agents/coder.md +56 -0
  10. package/payload/agents/decomposer.md +70 -0
  11. package/payload/agents/docs-sync.md +115 -0
  12. package/payload/agents/e2e-test-writer.md +47 -0
  13. package/payload/agents/migration-reviewer.md +100 -0
  14. package/payload/agents/orchestrator.md +50 -0
  15. package/payload/agents/performance-reviewer.md +82 -0
  16. package/payload/agents/postmortem.md +83 -0
  17. package/payload/agents/release-mr.md +274 -0
  18. package/payload/agents/security-reviewer.md +122 -0
  19. package/payload/agents/test-fix.md +33 -0
  20. package/payload/agents/test-writer.md +40 -0
  21. package/payload/ci-templates/claude-pipeline.gitlab-ci.yml +233 -0
  22. package/payload/ci-templates/github/README.md +76 -0
  23. package/payload/ci-templates/github/claude-issue-pipeline.yml +141 -0
  24. package/payload/ci-templates/github/claude-pipeline.yml +141 -0
  25. package/payload/ci-templates/github/claude-test-fix.yml +104 -0
  26. package/payload/ci-templates/scripts/code.sh +114 -0
  27. package/payload/ci-templates/scripts/lib/issue-loop.sh +430 -0
  28. package/payload/ci-templates/scripts/lib/pipeline-common.sh +280 -0
  29. package/payload/ci-templates/scripts/lib/platform.sh +177 -0
  30. package/payload/ci-templates/scripts/lib/usage-capture.sh +110 -0
  31. package/payload/ci-templates/scripts/orchestrate.sh +294 -0
  32. package/payload/ci-templates/scripts/postmortem.sh +45 -0
  33. package/payload/ci-templates/scripts/review-fix.sh +90 -0
  34. package/payload/ci-templates/scripts/review.sh +93 -0
  35. package/payload/ci-templates/scripts/test-fix.sh +58 -0
  36. package/payload/skills/fix-review-findings/SKILL.md +79 -0
  37. package/payload/skills/fix-tests/SKILL.md +70 -0
  38. package/payload/skills/implement-issue/SKILL.md +62 -0
  39. package/payload/skills/init-pipeline-config/SKILL.md +96 -0
  40. package/payload/skills/postmortem-mr/SKILL.md +50 -0
  41. package/payload/skills/review-mr/SKILL.md +82 -0
  42. package/payload/skills/triage-issue/SKILL.md +74 -0
  43. package/payload/templates/pipeline-config.template.md +98 -0
  44. package/payload/templates/review_suppressions.template.md +25 -0
  45. package/payload/templates/spec-issue.template.md +64 -0
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: security-reviewer
3
+ description: Reviews code for security vulnerabilities (authentication bypass, authorization flaws, injection, tenant/data isolation leaks, CSRF misconfiguration, sensitive data exposure) using confidence-based filtering to report only confirmed issues
4
+ tools: Glob, Grep, LS, Read, NotebookRead, WebFetch, TodoWrite, WebSearch, KillShell, BashOutput
5
+ model: sonnet
6
+ color: red
7
+ ---
8
+
9
+ You are an expert security reviewer. Your primary responsibility is to identify security vulnerabilities with high precision. False positives waste developer time and erode trust in the review process.
10
+
11
+ ## Project configuration (read first)
12
+
13
+ Before doing anything else, read the project pipeline configuration file (path in the `PIPE_CONFIG_PATH` environment variable, default `.claude/pipeline-config.md`). It defines the project stack, git and platform conventions, label names, build and test commands, capacity limits, domain-specific checks, and a documentation map (topic -> file). Resolve every project-specific reference in this prompt through that file and the documents it links. If the config file does not exist, state that explicitly at the top of your output and continue with conservative, generic behavior.
14
+
15
+ ## Architecture Context
16
+
17
+ Before reviewing, read the security documents listed in the Documentation Map of the pipeline config (the security topic), plus the security entries in the Domain Checks section. These describe the project's authentication layers, role hierarchy, permission levels, tenant isolation mechanism, security-sensitive classes, and sensitive fields. Use these docs as the authoritative reference, do not rely on training data about the stack.
18
+
19
+ ## Review Scope
20
+
21
+ By default, review unstaged changes from `git diff`. The user or CI may specify different files, an MR/PR diff, or a scope to review. When a title, description, and linked issues are provided, use them to understand the **intent** of the change before judging the implementation.
22
+
23
+ ## Mandatory Security Checks
24
+
25
+ Apply the generic categories below. For each one, resolve the project-specific classes, filters, endpoints, and fields through the Domain Checks section and the security documents named in the pipeline config.
26
+
27
+ ### 1. Authentication bypass
28
+ - Overly broad public/permit-all rules on sensitive paths in the security configuration
29
+ - New endpoints not covered by the security filter chain
30
+ - The set of endpoints exempted from authentication must match the set the project intends to protect by API key or equivalent
31
+
32
+ ### 2. Authorization flaws
33
+ - Every handler that modifies data must be behind an authorization check or a role-gated path
34
+ - Verify role checks use the correct hierarchy level for the project
35
+ - Read the actual handler source, do not infer authorization from layer or naming
36
+
37
+ ### 3. CSRF misconfiguration
38
+ - When the project documents matching production and test policies, compare the actual exemption sets rather than assuming they match
39
+ - Only endpoints authenticated by a non-cookie mechanism (for example an API key) should be CSRF-exempt
40
+ - New form-submission endpoints must NOT be added to the exemption list
41
+
42
+ ### 4. Injection
43
+ - Direct string concatenation into SQL, JPQL, or other query languages
44
+ - User input used as query property names or identifiers
45
+ - Native or raw queries with interpolated parameters are critical
46
+ - Prefer parameterized queries and query-builder APIs
47
+
48
+ ### 5. Sensitive data in logs
49
+ - Passwords, tokens, API keys, secrets, session IDs, and any sensitive field named in the Domain Checks section
50
+ - Flag logging that emits a sensitive value without sanitization
51
+ - Correct pattern: log a context message plus the exception object, never the sensitive value itself
52
+
53
+ ### 6. Credential and hash handling
54
+ - Never re-encode a value already stored in the project's detected hash format; verify the format from configuration or library usage rather than assuming one algorithm
55
+ - Review encoding logic changes in the services named in the Domain Checks section
56
+ - Constant-time comparison for secrets, with null checks before the comparison call
57
+
58
+ ### 7. API key / token auth
59
+ - Where both a key and a secret are required, both must be validated, not just one
60
+ - New endpoints that should require API-key auth must be added to the protected set
61
+
62
+ ### 8. Tenant / data isolation leaks
63
+ - All queries for tenant-scoped or ownership-scoped entities must filter at the database query level
64
+ - Cross-tenant or cross-owner access via direct ID lookup that bypasses the permission filter is critical
65
+
66
+ ## Suppression Check (read before reporting anything)
67
+
68
+ Before reporting any issue, read the suppressions file (path in the Suppressions section of the pipeline config, default `.claude/memory/review_suppressions.md`). If the pattern you are about to flag matches an entry under "Security Review Suppressions", skip it. It is a documented intentional decision. Do not report suppressed patterns even if your confidence is 100.
69
+
70
+ ## Mandatory Verification Before Reporting
71
+
72
+ Before reporting any issue, you MUST verify the claim using your tools. Never report based on assumption or partial reading:
73
+
74
+ - **Endpoint protection claims**: Read the security configuration and confirm the endpoint's actual security chain before claiming it is unprotected.
75
+ - **Missing authorization claims**: Read the handler class and confirm the authorization check is actually absent, not just on a different line.
76
+ - **Injection claims**: Read the query code and confirm it uses string concatenation, not parameterization.
77
+ - **Config mismatch claims**: Read both the production and test security configuration and compare the actual exemption lists.
78
+ - **Test profile assumptions**: Do not assume test-profile configuration applies to production, verify the profile annotation or condition.
79
+
80
+ ### CI and automation scripts
81
+
82
+ For CI files, establish the trust boundary before judging a value. Issue and
83
+ MR/PR titles, bodies, comments, branch names, changed repository files, and code
84
+ checked out from a contributor branch are untrusted. Runner-generated numeric
85
+ IDs and fixed project paths may be trusted only when the platform documentation
86
+ guarantees their shape.
87
+
88
+ Read sibling scripts and the mapped CI documentation for context, but repeated
89
+ use is not evidence that a pattern is safe. Report a repeated pattern when there
90
+ is still a concrete injection, secret-exposure, permission, or persistence path.
91
+ Account for ephemeral containers when assessing persistence and cleanup impact,
92
+ without treating ephemerality as protection for credentials available during
93
+ the job.
94
+
95
+ If a source file is not available to read, explicitly state that and lower your confidence accordingly.
96
+
97
+ ## Confidence Scoring
98
+
99
+ Rate each potential issue on a scale from 0-100:
100
+
101
+ - **0**: Not confident at all, likely a false positive or pre-existing issue
102
+ - **25**: Somewhat confident, might be real but could be intentional design
103
+ - **50**: Moderately confident, real issue but low impact or unlikely to be exploited in practice
104
+ - **75**: Highly confident, verified this is a real vulnerability that could be exploited
105
+ - **100**: Absolutely certain, confirmed exploitable vulnerability with a clear attack path
106
+
107
+ **Only report issues with confidence >= 80.** Quality over quantity, one confirmed critical vulnerability is worth more than ten speculative warnings.
108
+
109
+ ## Output Guidance
110
+
111
+ Start by clearly stating what you are reviewing and the security context.
112
+
113
+ For each high-confidence issue, provide:
114
+ - Severity: **CRITICAL** (exploitable now) or **IMPORTANT** (defense-in-depth concern)
115
+ - Confidence score
116
+ - File path and line number
117
+ - Description of the vulnerability and attack scenario
118
+ - Concrete fix suggestion
119
+
120
+ Group issues by severity. If no high-confidence issues exist, confirm the code meets security standards with a brief summary of what was checked.
121
+
122
+ End with a **Security Posture Summary**, one paragraph assessing the overall security impact of the reviewed changes.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: test-fix
3
+ description: Fixes failing tests in pipeline merge requests. Reads failing test files and their production source classes, determines root cause, fixes implementation or test as needed, verifies compilation, and commits. Never pushes.
4
+ tools: Agent, Bash, Edit, Glob, Grep, LS, MultiEdit, NotebookRead, Read, Skill, TodoWrite, Write
5
+ model: sonnet
6
+ ---
7
+
8
+ You are the test-fix agent. Your job is to fix failing tests in a merge request, not to rewrite features.
9
+
10
+ ## Project configuration (read first)
11
+
12
+ Before doing anything else, read the project pipeline configuration file (path in the `PIPE_CONFIG_PATH` environment variable, default `.claude/pipeline-config.md`). It defines the project stack, git and platform conventions, label names, build and test commands, capacity limits, domain-specific checks, and a documentation map (topic -> file). Resolve every project-specific reference in this prompt through that file and the documents it links. If the config file does not exist, state that explicitly at the top of your output and continue with conservative, generic behavior.
13
+
14
+ ## Workflow
15
+
16
+ 1. **Read conventions**: Read `CLAUDE.md` and the testing document from the Documentation Map for project and testing conventions.
17
+ 2. **Understand failures**: The task prompt contains test failure details (class names, error messages, stack traces from the test reports).
18
+ 3. **Read the tests**: Open each failing test file and read it completely.
19
+ 4. **Read the source**: Read the production class(es) the test exercises. Confirm constructors, method signatures, and return types match what the test calls.
20
+ 5. **Fix the root cause**: If the superpowers plugin is available, use the `superpowers:systematic-debugging` skill to diagnose root cause before touching any code. Fix either the implementation or the test, whichever is wrong:
21
+ - If the test calls a method/constructor that no longer matches the production class → update the test
22
+ - If the implementation doesn't satisfy a valid test expectation → fix the implementation
23
+ - If it's a missing dependency or import → add it
24
+ 6. **Verify**: If the superpowers plugin is available, use the `superpowers:verification-before-completion` skill before claiming the fix is done. Run the compile commands from Build & Tests to confirm the fix compiles.
25
+ 7. **Commit**: `git add -A && git commit -m "Fix test errors"`. If the CI job provides an exact commit subject, use that instead (it drives fix-loop caps).
26
+ 8. **Stop**: Do NOT run `git push`. The CI script handles pushing.
27
+
28
+ ## Constraints
29
+
30
+ - Fix only what is causing failures. Do not refactor or improve unrelated code.
31
+ - Do not rewrite the whole feature.
32
+ - If a test is testing something that was intentionally removed, it is acceptable to remove or update the test. Explain why in the commit message.
33
+ - Read the testing document from the Documentation Map for project-specific test infrastructure rules and pitfalls before changing test code. It covers language-level traps (what counts as a valid argument versus a missing overload), mocking pitfalls (checked exceptions, proxy wrapping and its effect on exception handlers), and the exact limits of transactional rollback for test isolation (when data written by the code under test survives the rollback and needs manual cleanup). Follow the testing doc on these points, do not reason them out from first principles.
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: test-writer
3
+ description: Generates integration and unit tests that increase coverage for new or changed code, following the project's documented testing patterns, with a self-correcting compilation loop
4
+ tools: Agent, Bash, Edit, Glob, Grep, LS, MultiEdit, NotebookRead, Read, Skill, TodoWrite, Write
5
+ model: sonnet
6
+ color: green
7
+ ---
8
+
9
+ You are the test-writer agent. Your job is to write tests that increase coverage for new or changed code.
10
+
11
+ ## Project configuration (read first)
12
+
13
+ Before doing anything else, read the project pipeline configuration file (path in the `PIPE_CONFIG_PATH` environment variable, default `.claude/pipeline-config.md`). It defines the project stack, git and platform conventions, label names, build and test commands, capacity limits, domain-specific checks, and a documentation map (topic -> file). Resolve every project-specific reference in this prompt through that file and the documents it links. If the config file does not exist, state that explicitly at the top of your output and continue with conservative, generic behavior.
14
+
15
+ ## Workflow
16
+
17
+ 1. **Read conventions**: Read `CLAUDE.md` and the testing document from the Documentation Map completely before writing any test. The testing document contains the full test patterns, naming rules, test base class details, and common gotchas. If the superpowers plugin is available, use the `superpowers:test-driven-development` skill to guide the overall test-writing loop.
18
+ 2. **Read the source**: Open the production class(es) to test. Understand constructors, method signatures, dependencies, and return types completely before writing any test code.
19
+ 3. **Read existing tests**: Find and read tests in the same package or for similar classes. Reuse existing helpers and fixture utilities rather than inventing new setup patterns.
20
+ 4. **Choose test type**:
21
+ - **Unit test**: no framework context, dependencies mocked. Use for pure service/component logic with mockable dependencies.
22
+ - **Integration test**: extends the project's shared test base class, boots the framework context. Use for repository, service, or controller behavior that needs a real database.
23
+
24
+ Take the exact naming conventions and base class details from the testing document and the Build & Tests section of the config.
25
+ 5. **Write tests** following the project's documented patterns.
26
+ 6. **Verify**: Run the compile commands from Build & Tests. If compilation fails, read the error, fix the root cause, and retry. Allow up to 3 fix attempts.
27
+ 7. **Commit**: `git add -A && git commit -m "Add coverage tests"`. If the CI job provides an exact commit subject, use that instead (it drives fix-loop caps).
28
+ 8. **Stop**: Do NOT run `git push`. The CI script handles pushing.
29
+
30
+ ## Critical Rules (Non-Negotiable)
31
+
32
+ Read the testing document from the Documentation Map for project-specific test infrastructure rules and pitfalls. Treat its constraints as non-negotiable. In particular, resolve these questions from that document before writing tests:
33
+
34
+ - Which annotations or setup patterns are forbidden because they break test-context caching or restart shared containers per class.
35
+ - When to use transactional rollback for test isolation and when it provides no benefit or does not apply at all: follow the testing doc, do not guess.
36
+ - Which fixture helpers to use for creating test entities instead of raw repository calls.
37
+ - Which external components must be mocked in integration tests.
38
+ - What mutating HTTP requests need in tests (security tokens, headers).
39
+ - Which cleanup steps are required when data is written outside a rolled-back transaction.
40
+ - Pitfalls when mocking methods that throw checked exceptions.
@@ -0,0 +1,233 @@
1
+ # =============================================================================
2
+ # Claude ci-agent-platform: GitLab CI template (tier 1)
3
+ # =============================================================================
4
+ # Include this file from your project's .gitlab-ci.yml:
5
+ #
6
+ # include:
7
+ # - local: .claude-pipeline/claude-pipeline.gitlab-ci.yml # vendored copy
8
+ #
9
+ # Your project's `stages:` must include `test` and `review` for the review loop:
10
+ # stages: [build, test, review, deploy]
11
+ # The issue -> code loop needs `orchestrate` and `code` as well (see the note
12
+ # further down); wiring all four up front costs nothing, since a stage with no
13
+ # job is skipped:
14
+ # stages: [orchestrate, code, build, test, review, deploy]
15
+ # The `test` job that produces JUnit/coverage artifacts stays in YOUR project.
16
+ # This template only reads its results (see the test-fix job's `needs:`).
17
+ #
18
+ # Override any PIPE_ variable in your own variables: block. Secrets
19
+ # (ANTHROPIC_API_KEY, PIPE_BOT_TOKEN) are set as masked CI variables, never
20
+ # here. Do NOT re-declare a secret in a job's variables: block as a same-name
21
+ # self-reference (FOO: "$FOO"): on GitLab it resolves to an empty string and
22
+ # shadows the real project variable (pilot 2 finding, P6). Project variables
23
+ # reach every job automatically. The GitHub workflows are different: there the
24
+ # explicit env: mapping from secrets is required.
25
+ # The jobs call the runner scripts, which call `claude "/<skill>"`.
26
+ # All reasoning lives in the skills, this file is triggers plus plumbing.
27
+ # =============================================================================
28
+
29
+ variables:
30
+ # --- Where the runner scripts live (vendored copy path) --------------------
31
+ PIPE_SCRIPTS_DIR: ".claude-pipeline/scripts"
32
+
33
+ # --- CI image (see ci-templates decision note) -----------------------------
34
+ # Must provide: node + npm, git, curl. jq and claude-code are installed in
35
+ # before_script when missing. The runner scripts talk to the GitLab API with
36
+ # curl and jq directly, so no glab is needed in the image; glab is only used
37
+ # interactively, by the install wizard.
38
+ # Python caveat (E2E finding N-7): node:22-bookworm ships python3 but NOT
39
+ # pip and NOT ensurepip ("python3 -m venv" fails). A Python project's
40
+ # PIPE_VERIFY_CMD must bootstrap pip first, e.g.
41
+ # "apt-get update -qq && apt-get install -y -qq python3-pip && ...",
42
+ # or the project overrides PIPE_CI_IMAGE with a stack image. The onboarding
43
+ # wizard composes the verify command accordingly. Override the image only
44
+ # when the fix/coder jobs need a toolchain the image lacks (JDK, Go, ...).
45
+ PIPE_CI_IMAGE: "node:22-bookworm"
46
+
47
+ # --- Platform + config -----------------------------------------------------
48
+ # PIPE_PLATFORM is autodetected from GITLAB_CI now, so setting it is optional.
49
+ # It is kept here as an explicit, harmless override.
50
+ PIPE_PLATFORM: "gitlab"
51
+ PIPE_CONFIG_PATH: ".claude/pipeline-config.md"
52
+ PIPE_CONTEXT_DIR: "build/pipeline"
53
+
54
+ # --- Git model -------------------------------------------------------------
55
+ # Integration branch MRs target. Must be a LITERAL branch name: a nested
56
+ # variable like "$CI_DEFAULT_BRANCH" is NOT expanded inside rules:
57
+ # comparisons, so review/review-fix/test-fix would never be added to the
58
+ # pipeline (E2E finding N-3). The onboarding wizard writes the detected
59
+ # branch into the project's variables: block; override there, never here.
60
+ PIPE_TARGET_BRANCH: "main"
61
+ PIPE_BOT_USER: "" # leave empty: resolved from the token at runtime; set only to filter comments by a different account
62
+ PIPE_GIT_NAME: "Pipeline Bot" # coder commit identity (name)
63
+ PIPE_GIT_EMAIL: "bot@pipeline.ci" # coder commit identity (email)
64
+
65
+ # --- Lifecycle labels ------------------------------------------------------
66
+ # Neutral defaults. Override with your project's own label names in your
67
+ # variables: block (roles: ready / wip / stuck / blocker / blocked / decomposed).
68
+ PIPE_LABEL_READY: "pipe-ready"
69
+ PIPE_LABEL_WIP: "pipe-wip"
70
+ PIPE_LABEL_STUCK: "pipe-stuck"
71
+ PIPE_LABEL_BLOCKER: "pipe-blocker"
72
+ PIPE_LABEL_BLOCKED: "pipe-blocked" # issue waiting on a prerequisite
73
+ PIPE_LABEL_DECOMPOSED: "pipe-decomposed" # parent split into sub-issues
74
+
75
+ # --- Issue -> code loop ----------------------------------------------------
76
+ PIPE_CODER_CAP: "3" # max coder pipelines per orchestrate run
77
+ PIPE_ORCHESTRATE: "0" # set to "1" in the schedule to run orchestrate
78
+ PIPE_SPEC_TEMPLATE_PATH: ".gitlab/issue_templates/Spec.md"
79
+
80
+ # --- Build / verify --------------------------------------------------------
81
+ PIPE_VERIFY_CMD: "" # compile + unit tests, run after a fix
82
+ PIPE_COMPILE_CMD: "" # compile only (defaults to PIPE_VERIFY_CMD)
83
+ PIPE_TEST_REPORT_GLOB: "" # e.g. build/test-results/**/TEST-*.xml
84
+ PIPE_COVERAGE_SIGNAL: "" # path to a coverage-drop signal file
85
+
86
+ # --- Commit subjects (drive the fix-loop cap counters) ---------------------
87
+ PIPE_COMMIT_TESTFIX: "Fix test errors"
88
+ PIPE_COMMIT_REVIEWFIX: "Fix review findings"
89
+ PIPE_COMMIT_COVERAGE: "Add coverage tests"
90
+
91
+ # --- Caps + models ---------------------------------------------------------
92
+ PIPE_FIX_LOOP_CAP: "2"
93
+ # Main-loop model per job group, passed as `claude --model` by the runner.
94
+ # Aliases track the current model, same convention as the agent frontmatter.
95
+ # Subagents keep the models from their own frontmatter.
96
+ PIPE_MODEL_TRIAGE: "haiku"
97
+ PIPE_MODEL_CODE: "sonnet"
98
+ PIPE_MODEL_REVIEW: "sonnet"
99
+ PIPE_AGENT_ENV_ALLOWLIST: "" # credential-like env names the agent-run build must receive (comma-separated; prefer empty)
100
+
101
+ # --- Result files (defaults live under PIPE_CONTEXT_DIR) --------------------
102
+ PIPE_RESULT_REVIEW: "$PIPE_CONTEXT_DIR/code-review-result.txt"
103
+ PIPE_RESULT_REVIEWFIX: "$PIPE_CONTEXT_DIR/review-fix-result.json"
104
+
105
+ # --- Hidden base job: shared config + runtime variable mapping ---------------
106
+ # Maps GitLab's CI_ runtime variables onto the PIPE_ names the scripts read, and
107
+ # installs claude-code if the image does not ship it.
108
+ .claude-base:
109
+ image: $PIPE_CI_IMAGE
110
+ variables:
111
+ GIT_DEPTH: "0" # full history for diff base + cap counting
112
+ PIPE_API_URL: "$CI_API_V4_URL"
113
+ PIPE_PROJECT_ID: "$CI_PROJECT_ID"
114
+ PIPE_PROJECT_PATH: "$CI_PROJECT_PATH"
115
+ PIPE_SERVER_HOST: "$CI_SERVER_HOST"
116
+ PIPE_MR_IID: "$CI_MERGE_REQUEST_IID"
117
+ PIPE_SOURCE_BRANCH: "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
118
+ PIPE_HEAD_SHA: "$CI_COMMIT_SHA"
119
+ PIPE_TOKEN: "$PIPE_BOT_TOKEN"
120
+ PIPE_JOB_NAME: "$CI_JOB_NAME"
121
+ PIPE_JOB_ID: "$CI_JOB_ID"
122
+ PIPE_PIPELINE_ID: "$CI_PIPELINE_ID"
123
+ before_script:
124
+ # jq is a hard dependency of every runner script. GitHub-hosted runners
125
+ # ship it, plain docker images (node:22-bookworm) do not, so install it
126
+ # here (finding from the GitLab pilot: silent HTTP 400s + exit 127).
127
+ - command -v jq >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y -qq jq)
128
+ - command -v claude >/dev/null 2>&1 || npm install -g @anthropic-ai/claude-code
129
+ artifacts:
130
+ paths:
131
+ - $PIPE_CONTEXT_DIR/metrics/
132
+ when: always
133
+ expire_in: 60 days
134
+
135
+ # =============================================================================
136
+ # review: run the automated review on a non-draft MR that changes code.
137
+ # =============================================================================
138
+ review:
139
+ extends: .claude-base
140
+ stage: review
141
+ timeout: 20m
142
+ script:
143
+ - bash "$PIPE_SCRIPTS_DIR/review.sh"
144
+ artifacts:
145
+ paths:
146
+ - $PIPE_CONTEXT_DIR/metrics/
147
+ reports:
148
+ dotenv: $PIPE_CONTEXT_DIR/review.env
149
+ when: always
150
+ expire_in: 60 days
151
+ rules:
152
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $PIPE_TARGET_BRANCH && $CI_MERGE_REQUEST_TITLE !~ /^Draft:/'
153
+ when: on_success
154
+
155
+ # =============================================================================
156
+ # review-fix: on review failure (REVIEW_HAS_BUGS), fix the confirmed bugs.
157
+ # Gated to wip MRs. Reads REVIEW_HAS_BUGS from the review job's dotenv artifact.
158
+ # =============================================================================
159
+ review-fix:
160
+ extends: .claude-base
161
+ stage: review
162
+ timeout: 60m
163
+ needs:
164
+ - job: review
165
+ artifacts: true
166
+ optional: true
167
+ variables:
168
+ GIT_STRATEGY: clone
169
+ script:
170
+ - bash "$PIPE_SCRIPTS_DIR/review-fix.sh"
171
+ allow_failure: true
172
+ rules:
173
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $PIPE_TARGET_BRANCH && $CI_MERGE_REQUEST_LABELS =~ $PIPE_LABEL_WIP'
174
+ when: on_failure
175
+
176
+ # =============================================================================
177
+ # orchestrate: triage ready issues and fire the coder (issue -> code loop).
178
+ # Runs on a scheduled pipeline that sets PIPE_ORCHESTRATE=1 (kept off by default
179
+ # so a schedule turns it on deliberately, for spend control). Needs a pipeline
180
+ # trigger token in PIPE_TRIGGER_TOKEN (set as a protected/masked CI variable) to
181
+ # start the child `code` pipeline.
182
+ #
183
+ # To enable the issue loop, add `orchestrate` and `code` to your `stages:`.
184
+ # =============================================================================
185
+ orchestrate:
186
+ extends: .claude-base
187
+ stage: orchestrate
188
+ timeout: 30m
189
+ variables:
190
+ GIT_STRATEGY: clone
191
+ script:
192
+ - bash "$PIPE_SCRIPTS_DIR/orchestrate.sh"
193
+ rules:
194
+ - if: '$CI_PIPELINE_SOURCE == "schedule" && $PIPE_ORCHESTRATE == "1"'
195
+ - if: '$CI_PIPELINE_SOURCE == "web" && $PIPE_ORCHESTRATE == "1"'
196
+
197
+ # =============================================================================
198
+ # code: implement one issue and open the MR (issue -> code loop).
199
+ # Triggered by orchestrate via the Pipeline Trigger API with CODER_ISSUE and
200
+ # CODER_BRANCH set. The coder agent runs with --dangerously-skip-permissions on
201
+ # this isolated runner (and non-root where the image allows); see code.sh.
202
+ # =============================================================================
203
+ code:
204
+ extends: .claude-base
205
+ stage: code
206
+ timeout: 45m
207
+ variables:
208
+ GIT_STRATEGY: clone
209
+ script:
210
+ - bash "$PIPE_SCRIPTS_DIR/code.sh"
211
+ rules:
212
+ - if: '$CODER_ISSUE && $CODER_BRANCH'
213
+
214
+ # =============================================================================
215
+ # test-fix: on failure of YOUR project's `test` job, on a wip MR, fix tests /
216
+ # compilation / coverage. Consumes the test job's artifacts via needs.
217
+ # =============================================================================
218
+ test-fix:
219
+ extends: .claude-base
220
+ stage: test
221
+ timeout: 60m
222
+ needs:
223
+ - job: test
224
+ artifacts: true
225
+ optional: true
226
+ variables:
227
+ GIT_STRATEGY: clone
228
+ script:
229
+ - bash "$PIPE_SCRIPTS_DIR/test-fix.sh"
230
+ allow_failure: true
231
+ rules:
232
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $PIPE_TARGET_BRANCH && $CI_MERGE_REQUEST_LABELS =~ $PIPE_LABEL_WIP'
233
+ when: on_failure
@@ -0,0 +1,76 @@
1
+ # GitHub Actions variant: concept mapping
2
+
3
+ The skills and agents are identical across platforms. Only the CI wiring and a
4
+ few names differ. The runner scripts in `../scripts/` are shared: they read
5
+ `$PIPE_PLATFORM` and branch on it (see `scripts/lib/platform.sh`).
6
+
7
+ | Concept | GitLab | GitHub Actions |
8
+ |---|---|---|
9
+ | Change unit | Merge Request (MR) | Pull Request (PR) |
10
+ | CLI used by the runner | `glab` / GitLab REST via `curl` | `gh api` |
11
+ | Config values | CI/CD variables | repository/org **Variables** (`vars.*`) |
12
+ | Secrets | protected/masked CI variables | **Secrets** (`secrets.*`) |
13
+ | Run after a job fails | `when: on_failure` | `needs:` + `if: ${{ failure() }}` (same workflow) |
14
+ | Cross-workflow trigger | pipeline artifact + `needs` | `on: workflow_run` (`claude-test-fix.yml`) |
15
+ | Gate a downstream job on a runtime value | `dotenv` artifact (`review.env`) | job `outputs` (`needs.review.outputs.has_bugs`) |
16
+ | Block the merge | job exits non-zero | required status check fails |
17
+ | Incremental diff base | MR versions API | `github.event.before` on `synchronize` |
18
+ | Bot identity for push | project/personal access token | bot **PAT** (`PIPE_BOT_TOKEN`) |
19
+
20
+ ## Gaps where the platforms do not map one to one
21
+
22
+ - **Push must re-trigger the pipeline.** GitHub's default `GITHUB_TOKEN` does not
23
+ trigger workflows on its own push (loop protection). The fix loop therefore
24
+ needs a bot PAT in `PIPE_BOT_TOKEN` so a fix commit re-runs review/tests.
25
+ GitLab has no such restriction, but a bot token is still cleaner than the
26
+ pipeline's own `CI_JOB_TOKEN`.
27
+ - **test-fix hangs off your test workflow.** GitLab evaluates `on_failure`
28
+ within one pipeline. GitHub keeps your test workflow separate, so `test-fix`
29
+ runs via `workflow_run`. It downloads the failed run's `test-reports`
30
+ artifact, so your test workflow must upload the reports under that name (or
31
+ set `PIPE_TEST_ARTIFACT`). If you prefer one workflow, drop this job into your
32
+ test workflow instead:
33
+
34
+ ```yaml
35
+ claude-test-fix:
36
+ needs: [test]
37
+ if: ${{ failure() && contains(github.event.pull_request.labels.*.name, vars.PIPE_LABEL_WIP) }}
38
+ runs-on: ubuntu-latest
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+ with: { ref: ${{ github.event.pull_request.head.ref }}, fetch-depth: 0, token: ${{ secrets.PIPE_BOT_TOKEN }} }
42
+ - run: command -v claude >/dev/null 2>&1 || npm install -g @anthropic-ai/claude-code
43
+ - env: { ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}, GH_TOKEN: ${{ secrets.PIPE_BOT_TOKEN }} }
44
+ run: bash "$PIPE_SCRIPTS_DIR/test-fix.sh"
45
+ ```
46
+ - **Fork PRs.** `workflow_run.pull_requests` is empty for PRs from forks (a
47
+ GitHub security boundary), so `claude-test-fix.yml` skips them. review and
48
+ review-fix in `claude-pipeline.yml` still run, but secrets are not exposed to
49
+ fork PRs by default, so the paid steps are effectively same-repo only.
50
+ - **Draft filtering.** GitLab reads `$CI_MERGE_REQUEST_TITLE !~ /^Draft:/`.
51
+ GitHub has a first-class `draft` flag, used in the review job `if:`.
52
+
53
+ ## Issue-to-code loop (claude-issue-pipeline.yml)
54
+
55
+ | Concept | GitLab | GitHub Actions |
56
+ |---|---|---|
57
+ | Orchestrate trigger | scheduled pipeline (`PIPE_ORCHESTRATE=1`) | `workflow_dispatch`, manual during the pilot (decision D2); cron is provided commented out |
58
+ | Orchestrate -> code | Pipeline Trigger API (`PIPE_TRIGGER_TOKEN`) | `workflow_dispatch` of the same workflow with `inputs.coder_issue` + `inputs.coder_branch` (bot PAT) |
59
+ | Labels | project-level (`/projects/:id/labels`) | repo-level (`/repos/:repo/labels`) |
60
+ | Blocking links | native `is_blocked_by` links | text convention `Blocked by #N` in the body (decision D1) |
61
+ | Decomposed-parent children | native `blocks` links | machine marker `<!-- pipe-children: #a #b -->` in the parent comment |
62
+ | MR/PR labels | set at creation | set after creation via the issues API |
63
+ | Delete source branch | `remove_source_branch: true` | repo setting "Automatically delete head branches" |
64
+
65
+ Both platforms share `orchestrate.sh`, `code.sh`, and `lib/issue-loop.sh`. The
66
+ platform is autodetected from `GITHUB_ACTIONS` / `GITLAB_CI`, so `PIPE_PLATFORM`
67
+ does not need setting.
68
+
69
+ ### Gaps in the GitHub issue loop
70
+
71
+ - **Decomposed-parent auto-close is best-effort.** With no native child links,
72
+ the release poll parses the `<!-- pipe-children: ... -->` marker the
73
+ decomposition comment embeds. If a human edits that comment away, the parent
74
+ will not auto-close. Native sub-issues (REST/GraphQL) are the future upgrade.
75
+ - **Milestone inheritance is not carried** onto the PR (kept simple for the
76
+ pilot); labels are inherited.
@@ -0,0 +1,141 @@
1
+ # =============================================================================
2
+ # Claude ci-agent-platform: GitHub Actions workflow (issue -> code loop)
3
+ # =============================================================================
4
+ # Copy this to .github/workflows/claude-issue-pipeline.yml. It mirrors the
5
+ # GitLab `orchestrate` and `code` jobs in a single workflow, both driven by
6
+ # workflow_dispatch:
7
+ #
8
+ # - No inputs (or coder_issue empty) -> the `orchestrate` job runs: it triages
9
+ # ready issues and dispatches this same workflow with coder inputs.
10
+ # - coder_issue + coder_branch set -> the `code` job runs: it implements the
11
+ # issue and opens a PR.
12
+ #
13
+ # Decision D2: orchestrate is manual only (workflow_dispatch), no cron, so paid
14
+ # runs stay under human control during the pilot. A cron schedule is provided
15
+ # commented out below for when you are ready.
16
+ #
17
+ # Decision D1: GitHub has no native "is blocked by" issue links, so this loop
18
+ # expresses dependencies with the text convention "Blocked by #N" in the issue
19
+ # body. The release poll reads it back. Native sub-issues are a future upgrade.
20
+ #
21
+ # Configuration:
22
+ # - Repository/org VARIABLES: PIPE_TARGET_BRANCH, PIPE_LABEL_* , PIPE_CODER_CAP,
23
+ # PIPE_SPEC_TEMPLATE_PATH, PIPE_GIT_NAME, PIPE_GIT_EMAIL, etc.
24
+ # - SECRETS: ANTHROPIC_API_KEY, PIPE_BOT_TOKEN (a bot PAT with issues +
25
+ # contents + pull-requests + actions write). The bot PAT is required so the
26
+ # coder's push and the orchestrate -> code dispatch re-trigger workflows;
27
+ # the default GITHUB_TOKEN cannot.
28
+ # - Vendor the ci-agent-platform repository's ci-templates/scripts/ into your
29
+ # repo (PIPE_SCRIPTS_DIR).
30
+ # =============================================================================
31
+
32
+ name: claude-issue-pipeline
33
+
34
+ on:
35
+ workflow_dispatch:
36
+ inputs:
37
+ coder_issue:
38
+ description: "Issue number to implement. Leave empty to run orchestrate (triage)."
39
+ required: false
40
+ default: ""
41
+ coder_branch:
42
+ description: "Branch for the coder (required together with coder_issue)."
43
+ required: false
44
+ default: ""
45
+ # Enable scheduled orchestrate when the pilot is over (spend control). The
46
+ # orchestrate job's `if:` also requires coder_issue to be empty, which a
47
+ # schedule event satisfies.
48
+ # schedule:
49
+ # - cron: "30 23 * * 1-5" # 23:30 UTC on weekdays
50
+
51
+ permissions:
52
+ contents: write
53
+ issues: write
54
+ pull-requests: write
55
+
56
+ env:
57
+ PIPE_SCRIPTS_DIR: ".claude-pipeline/scripts"
58
+ # PIPE_PLATFORM is autodetected from GITHUB_ACTIONS; no need to set it.
59
+ PIPE_CONFIG_PATH: ".claude/pipeline-config.md"
60
+ PIPE_CONTEXT_DIR: "build/pipeline"
61
+ # On `schedule` events the payload has no repository object, so the middle
62
+ # term is empty there; set vars.PIPE_TARGET_BRANCH when the default branch
63
+ # is not main and the cron trigger is used.
64
+ PIPE_TARGET_BRANCH: ${{ vars.PIPE_TARGET_BRANCH || github.event.repository.default_branch || 'main' }}
65
+ PIPE_LABEL_READY: ${{ vars.PIPE_LABEL_READY || 'pipe-ready' }}
66
+ PIPE_LABEL_WIP: ${{ vars.PIPE_LABEL_WIP || 'pipe-wip' }}
67
+ PIPE_LABEL_STUCK: ${{ vars.PIPE_LABEL_STUCK || 'pipe-stuck' }}
68
+ PIPE_LABEL_BLOCKER: ${{ vars.PIPE_LABEL_BLOCKER || 'pipe-blocker' }}
69
+ PIPE_LABEL_BLOCKED: ${{ vars.PIPE_LABEL_BLOCKED || 'pipe-blocked' }}
70
+ PIPE_LABEL_DECOMPOSED: ${{ vars.PIPE_LABEL_DECOMPOSED || 'pipe-decomposed' }}
71
+ PIPE_CODER_CAP: ${{ vars.PIPE_CODER_CAP || '3' }}
72
+ PIPE_ISSUE_SCAN: ${{ vars.PIPE_ISSUE_SCAN || '20' }}
73
+ PIPE_SPEC_TEMPLATE_PATH: ${{ vars.PIPE_SPEC_TEMPLATE_PATH || '.github/ISSUE_TEMPLATE/spec.md' }}
74
+ PIPE_GIT_NAME: ${{ vars.PIPE_GIT_NAME || 'Pipeline Bot' }}
75
+ PIPE_GIT_EMAIL: ${{ vars.PIPE_GIT_EMAIL || 'bot@pipeline.ci' }}
76
+ PIPE_MODEL_TRIAGE: ${{ vars.PIPE_MODEL_TRIAGE || 'haiku' }}
77
+ PIPE_MODEL_CODE: ${{ vars.PIPE_MODEL_CODE || 'sonnet' }}
78
+ PIPE_AGENT_ENV_ALLOWLIST: ${{ vars.PIPE_AGENT_ENV_ALLOWLIST || '' }}
79
+ # Runtime mapping onto the PIPE_ names the scripts read.
80
+ PIPE_REPO: ${{ github.repository }}
81
+ PIPE_PROJECT_PATH: ${{ github.repository }}
82
+ PIPE_SERVER_HOST: "github.com"
83
+ PIPE_CODE_WORKFLOW: "claude-issue-pipeline.yml"
84
+
85
+ jobs:
86
+ # ---------------------------------------------------------------------------
87
+ # orchestrate: triage ready issues, dispatch the code job for actionable ones.
88
+ # ---------------------------------------------------------------------------
89
+ orchestrate:
90
+ if: ${{ github.event.inputs.coder_issue == '' }}
91
+ runs-on: ubuntu-latest
92
+ timeout-minutes: 30
93
+ steps:
94
+ - uses: actions/checkout@v4
95
+ with:
96
+ fetch-depth: 0
97
+ token: ${{ secrets.PIPE_BOT_TOKEN }}
98
+ - name: Install claude-code
99
+ run: command -v claude >/dev/null 2>&1 || npm install -g @anthropic-ai/claude-code
100
+ - name: Run orchestrate
101
+ env:
102
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
103
+ GH_TOKEN: ${{ secrets.PIPE_BOT_TOKEN }}
104
+ run: bash "$PIPE_SCRIPTS_DIR/orchestrate.sh"
105
+ - name: Upload metrics
106
+ if: always()
107
+ uses: actions/upload-artifact@v4
108
+ with:
109
+ name: orchestrate-metrics
110
+ path: ${{ env.PIPE_CONTEXT_DIR }}/metrics/
111
+ if-no-files-found: ignore
112
+
113
+ # ---------------------------------------------------------------------------
114
+ # code: implement one issue and open a PR.
115
+ # ---------------------------------------------------------------------------
116
+ code:
117
+ if: ${{ github.event.inputs.coder_issue != '' }}
118
+ runs-on: ubuntu-latest
119
+ timeout-minutes: 45
120
+ steps:
121
+ - uses: actions/checkout@v4
122
+ with:
123
+ ref: ${{ env.PIPE_TARGET_BRANCH }}
124
+ fetch-depth: 0
125
+ token: ${{ secrets.PIPE_BOT_TOKEN }}
126
+ - name: Install claude-code
127
+ run: command -v claude >/dev/null 2>&1 || npm install -g @anthropic-ai/claude-code
128
+ - name: Run code
129
+ env:
130
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
131
+ GH_TOKEN: ${{ secrets.PIPE_BOT_TOKEN }}
132
+ CODER_ISSUE: ${{ github.event.inputs.coder_issue }}
133
+ CODER_BRANCH: ${{ github.event.inputs.coder_branch }}
134
+ run: bash "$PIPE_SCRIPTS_DIR/code.sh"
135
+ - name: Upload metrics
136
+ if: always()
137
+ uses: actions/upload-artifact@v4
138
+ with:
139
+ name: code-metrics
140
+ path: ${{ env.PIPE_CONTEXT_DIR }}/metrics/
141
+ if-no-files-found: ignore