@neikyun/ciel 6.11.2 → 6.13.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.
- package/assets/.claude/agents/ciel-critic.md +71 -12
- package/assets/.claude/agents/ciel-explorer.md +59 -18
- package/assets/.claude/agents/ciel-improver.md +6 -3
- package/assets/.claude/agents/ciel-researcher.md +85 -25
- package/assets/.claude/hooks/block-destructive.sh +2 -2
- package/assets/.claude/hooks/check-test-first.sh +2 -2
- package/assets/.claude/hooks/memory-bootstrap.sh +0 -0
- package/assets/.claude/hooks/memory-engine.py +82 -15
- package/assets/.claude/hooks/post-tool-write.sh +32 -0
- package/assets/.claude/hooks/pre-agent-gate.sh +11 -6
- package/assets/.claude/hooks/pre-compact.sh +18 -0
- package/assets/.claude/hooks/pre-tool-write.sh +56 -31
- package/assets/.claude/hooks/session-start.sh +22 -1
- package/assets/.claude/hooks/session-version-check.sh +1 -1
- package/assets/.claude/hooks/stop.sh +104 -0
- package/assets/.claude/hooks/subagent-stop.sh +54 -0
- package/assets/.claude/hooks/track-file.sh +2 -2
- package/assets/.claude/hooks/user-prompt-submit.sh +11 -15
- package/assets/.claude/settings.json +18 -4
- package/assets/AGENTS.md +1 -1
- package/assets/CLAUDE.md +103 -175
- package/assets/commands/ciel-audit.md +58 -399
- package/assets/commands/ciel-create-skill.md +24 -38
- package/assets/commands/ciel-eval.md +25 -37
- package/assets/commands/ciel-init.md +36 -126
- package/assets/commands/ciel-status.md +22 -19
- package/assets/commands/ciel-update.md +20 -39
- package/assets/platforms/opencode/.opencode/agents/ciel-researcher.md +71 -895
- package/assets/platforms/opencode/.opencode/commands/ciel-audit.md +58 -296
- package/assets/platforms/opencode/.opencode/commands/ciel-create-skill.md +24 -46
- package/assets/platforms/opencode/.opencode/commands/ciel-eval.md +25 -45
- package/assets/platforms/opencode/.opencode/commands/ciel-init.md +36 -131
- package/assets/platforms/opencode/.opencode/commands/ciel-status.md +22 -24
- package/assets/platforms/opencode/.opencode/commands/ciel-update.md +20 -40
- package/assets/platforms/opencode/AGENTS.md +4 -4
- package/assets/rules/security.md +30 -0
- package/assets/rules/testing.md +23 -0
- package/assets/skills/agile/SKILL.md +42 -0
- package/assets/skills/alerting/SKILL.md +55 -0
- package/assets/skills/api-design/SKILL.md +46 -0
- package/assets/skills/appsec/SKILL.md +43 -0
- package/assets/skills/architecture/SKILL.md +74 -0
- package/assets/skills/backend/SKILL.md +41 -0
- package/assets/skills/backup-recovery/SKILL.md +42 -0
- package/assets/skills/caching/SKILL.md +44 -0
- package/assets/skills/cdn/SKILL.md +42 -0
- package/assets/skills/chaos/SKILL.md +41 -0
- package/assets/skills/cicd-pipeline/SKILL.md +56 -0
- package/assets/skills/cloud/SKILL.md +42 -0
- package/assets/skills/code-quality/SKILL.md +42 -0
- package/assets/skills/code-review/SKILL.md +41 -0
- package/assets/skills/communication/SKILL.md +42 -0
- package/assets/skills/containers/SKILL.md +42 -0
- package/assets/skills/cqrs/SKILL.md +41 -0
- package/assets/skills/crypto/SKILL.md +46 -0
- package/assets/skills/data-engineering/SKILL.md +42 -0
- package/assets/skills/database-design/SKILL.md +46 -0
- package/assets/skills/ddd/SKILL.md +45 -0
- package/assets/skills/deployment-strategies/SKILL.md +51 -0
- package/assets/skills/desktop/SKILL.md +42 -0
- package/assets/skills/devsecops/SKILL.md +43 -0
- package/assets/skills/event-driven/SKILL.md +46 -0
- package/assets/skills/frontend/SKILL.md +41 -0
- package/assets/skills/functional/SKILL.md +42 -0
- package/assets/skills/high-availability/SKILL.md +42 -0
- package/assets/skills/iac/SKILL.md +46 -0
- package/assets/skills/logging/SKILL.md +46 -0
- package/assets/skills/meta/ciel-improve/SKILL.md +127 -0
- package/assets/skills/meta/learnings-capture/SKILL.md +105 -0
- package/assets/skills/meta/patch-spec/patch-spec.md +50 -0
- package/assets/skills/meta/skill-creator/SKILL.md +115 -0
- package/assets/skills/meta/skill-freshness-auditor/SKILL.md +164 -0
- package/assets/skills/meta/skill-variant-evaluator/SKILL.md +100 -0
- package/assets/skills/meta/skills-first-design-auditor/SKILL.md +192 -0
- package/assets/skills/ml-engineering/SKILL.md +42 -0
- package/assets/skills/mobile/SKILL.md +42 -0
- package/assets/skills/monitoring/SKILL.md +54 -0
- package/assets/skills/networking/SKILL.md +42 -0
- package/assets/skills/nosql/SKILL.md +41 -0
- package/assets/skills/oop-solid/SKILL.md +42 -0
- package/assets/skills/performance/SKILL.md +41 -0
- package/assets/skills/reactive/SKILL.md +42 -0
- package/assets/skills/release-management/SKILL.md +51 -0
- package/assets/skills/research/fact-check-claims/SKILL.md +98 -0
- package/assets/skills/research/research-forums/SKILL.md +103 -0
- package/assets/skills/research/research-github-issues/SKILL.md +103 -0
- package/assets/skills/research/research-web-sources/SKILL.md +108 -0
- package/assets/skills/research/synthesize-findings/SKILL.md +112 -0
- package/assets/skills/research/validate-source-credibility/SKILL.md +103 -0
- package/assets/skills/resilience/SKILL.md +41 -0
- package/assets/skills/serverless/SKILL.md +42 -0
- package/assets/skills/servers/SKILL.md +41 -0
- package/assets/skills/sql/SKILL.md +45 -0
- package/assets/skills/supply-chain/SKILL.md +41 -0
- package/assets/skills/system-design/SKILL.md +91 -0
- package/assets/skills/tech-leadership/SKILL.md +46 -0
- package/assets/skills/testing/SKILL.md +41 -0
- package/assets/skills/tracing/SKILL.md +36 -0
- package/assets/skills/utility/branch-cleaner/SKILL.md +195 -0
- package/assets/skills/utility/branch-setup/SKILL.md +144 -0
- package/assets/skills/utility/changelog-updater/SKILL.md +125 -0
- package/assets/skills/utility/commit-writer/SKILL.md +154 -0
- package/assets/skills/utility/issue-closer/SKILL.md +106 -0
- package/assets/skills/utility/issue-creator/SKILL.md +200 -0
- package/assets/skills/utility/pr-merger/SKILL.md +189 -0
- package/assets/skills/utility/pr-opener/SKILL.md +180 -0
- package/assets/skills/utility/release-publisher/SKILL.md +224 -0
- package/assets/skills/workflow/ciel-dev-process/SKILL.md +94 -0
- package/assets/skills/workflow/faire-gatekeeper/SKILL.md +3 -1
- package/assets/skills/workflow/prouver-verifier/SKILL.md +11 -2
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +11 -2
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/claude.d.ts.map +1 -1
- package/dist/cli/claude.js +0 -2
- package/dist/cli/claude.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +11 -2
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/opencode.d.ts.map +1 -1
- package/dist/cli/opencode.js +2 -1
- package/dist/cli/opencode.js.map +1 -1
- package/package.json +1 -1
- package/assets/commands/ciel-migrate.md +0 -35
- package/assets/commands/ciel-refresh.md +0 -91
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-closer
|
|
3
|
+
description: Closes GitHub issues with a structured evidence comment — what was fixed, concrete observed staging evidence (logs/curl/DOM — NOT code diffs), and PR/SHA reference. Enforces closure gate from prouver-verifier. Never closes without evidence.
|
|
4
|
+
allowed-tools: Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# issue-closer — Structured issue closure
|
|
8
|
+
|
|
9
|
+
## What this covers
|
|
10
|
+
Implements the PROUVER closure gate: before any issue is marked closed, an evidence comment must be posted. Closing without evidence is lying to future-you.
|
|
11
|
+
|
|
12
|
+
## Core principle
|
|
13
|
+
**No evidence, no closure.** A code diff proves you wrote code. Staging evidence proves it works. Only the latter closes an issue.
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
- Issue number(s)
|
|
18
|
+
- Fix description (1 line)
|
|
19
|
+
- Concrete evidence: staging log excerpt, curl output, DOM snapshot, or screenshot — NOT code diff
|
|
20
|
+
- PR number or commit SHA that contains the fix
|
|
21
|
+
|
|
22
|
+
## Process
|
|
23
|
+
|
|
24
|
+
### 1. Check current state
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
gh issue view <N> --json state,comments
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If already closed AND evidence comment exists → no action needed.
|
|
31
|
+
If already closed AND no evidence comment → post evidence comment (closure without evidence = not closed).
|
|
32
|
+
If open → post evidence comment + close.
|
|
33
|
+
|
|
34
|
+
### 2. Post evidence comment
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
Fixed: <1-line description>
|
|
38
|
+
|
|
39
|
+
**Evidence** (from staging):
|
|
40
|
+
<concrete log excerpt / curl output / DOM snapshot / screenshot>
|
|
41
|
+
|
|
42
|
+
PR: #<N>
|
|
43
|
+
Commit: <SHA>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Use `gh issue comment <N> --body "$(cat <<'EOF' ... EOF)"` for formatting.
|
|
47
|
+
|
|
48
|
+
### 3. Close if still open
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
gh issue close <N> --reason completed
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 4. Confirm
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
gh issue view <N> --json state,comments
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
State: `closed`. Last comment: evidence format. → DONE.
|
|
61
|
+
|
|
62
|
+
## Common patterns
|
|
63
|
+
|
|
64
|
+
### Good closure comment
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
Fixed: prevent N+1 query in user dashboard endpoint
|
|
68
|
+
|
|
69
|
+
**Evidence** (from staging):
|
|
70
|
+
$ curl -s https://staging.example.com/api/dashboard | jq '.query_count'
|
|
71
|
+
12
|
|
72
|
+
(was 103 before fix — confirmed via pg_stat_statements)
|
|
73
|
+
|
|
74
|
+
PR: #568
|
|
75
|
+
Commit: a1b2c3d
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Bad closure comment
|
|
79
|
+
|
|
80
|
+
```markdown
|
|
81
|
+
Fixed in PR #568.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Problems: no evidence, no staging verification, just a code reference.
|
|
85
|
+
|
|
86
|
+
## Anti-patterns
|
|
87
|
+
|
|
88
|
+
- **Closing with code diff as evidence** — code diff proves you wrote code, not that it works
|
|
89
|
+
- **Closing without staging evidence** — always verify on staging first
|
|
90
|
+
- **Copy-paste evidence across issues** — if one PR closes 3 issues, each gets specific evidence
|
|
91
|
+
- **Auto-close via merge commit** — the auto-close doesn't add evidence. Close explicitly via this skill.
|
|
92
|
+
- **"It should work now"** — this is hope, not evidence
|
|
93
|
+
|
|
94
|
+
## How to verify
|
|
95
|
+
|
|
96
|
+
- [ ] Evidence comment posted before closure?
|
|
97
|
+
- [ ] Evidence is from staging (not local)?
|
|
98
|
+
- [ ] Evidence is concrete (log/curl/DOM, not "fixed in PR")?
|
|
99
|
+
- [ ] Issue state is `closed` with reason `completed`?
|
|
100
|
+
- [ ] Last comment matches evidence format (Fixed + Evidence + PR + Commit)?
|
|
101
|
+
|
|
102
|
+
## When triggered
|
|
103
|
+
|
|
104
|
+
- After `prouver-verifier` PROUVER step completes
|
|
105
|
+
- After PR merge when auto-close didn't add evidence
|
|
106
|
+
- User request: "close issue #N"
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-creator
|
|
3
|
+
description: Creates a GitHub issue from an RCA verdict, bug report, or feature request. Fills structured body (Problem / Root cause / Proposed fix / Acceptance criteria / Linked evidence). Uses `gh issue create`. Returns the issue number so downstream skills (branch-setup, commit-writer, pr-opener) can link to it. Mandatory on Critical tasks for audit trail, default-on for Standard tasks fixing a bug, skippable on Trivial. Inline — deterministic `gh` command.
|
|
4
|
+
allowed-tools: Bash, Read
|
|
5
|
+
context: inline
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# issue-creator — Every fix starts with an issue
|
|
9
|
+
|
|
10
|
+
"Audit trail first" is a 2026 compliance baseline (SOC 2, ISO 27001). Every production-affecting change needs a traceable reason. Ciel enforces this by creating the issue BEFORE opening a branch.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
TITLE: [1-line summary — imperative verb, ≤ 70 chars]
|
|
18
|
+
BODY_SOURCE: [rca-verdict | bug-report | feature-request]
|
|
19
|
+
RCA_VERDICT: [output from debug-reasoning-rca, if BODY_SOURCE=rca-verdict]
|
|
20
|
+
LABELS: [comma-separated, e.g., "bug,production,critical"]
|
|
21
|
+
ASSIGNEES: [optional, e.g., "@me"]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Auto-inference sources
|
|
25
|
+
|
|
26
|
+
- **TITLE** → from RCA VERDICT symptom (1 sentence) or user prompt's core ask
|
|
27
|
+
- **LABELS** → infer from Ciel depth: Critical → `bug,critical`, Standard + bug intent → `bug`, feature intent → `enhancement`
|
|
28
|
+
- **ASSIGNEES** → `@me` by default (the user running Ciel)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Preflight
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Verify gh CLI installed + authenticated
|
|
36
|
+
command -v gh || { echo "gh CLI not installed — abort"; exit 1; }
|
|
37
|
+
gh auth status 2>&1 | grep -q "Logged in" || { echo "gh not authenticated — run: gh auth login"; exit 1; }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If preflight fails, BLOCK the skill, instruct the user to install/authenticate.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Process
|
|
45
|
+
|
|
46
|
+
### 1. Check for duplicates
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Search open issues with similar title
|
|
50
|
+
gh issue list --state=open --search "<title keywords>" --limit 5
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If a matching open issue exists (≥70% keyword overlap), RETURN that issue number instead of creating a duplicate. Report: `[DUPE] Reusing existing issue #<N>`.
|
|
54
|
+
|
|
55
|
+
### 2. Build the body
|
|
56
|
+
|
|
57
|
+
Use this template (adapt per BODY_SOURCE):
|
|
58
|
+
|
|
59
|
+
**For rca-verdict (bug):**
|
|
60
|
+
```markdown
|
|
61
|
+
## Problem
|
|
62
|
+
|
|
63
|
+
<Symptom in 1 sentence>
|
|
64
|
+
|
|
65
|
+
## Repro
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
<exact command or "flaky — ~1/N runs">
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Root cause
|
|
72
|
+
|
|
73
|
+
<From RCA Phase 4 Semantic diff>
|
|
74
|
+
|
|
75
|
+
EXPECTED: <...>
|
|
76
|
+
ACTUAL: <...>
|
|
77
|
+
GAP: <...>
|
|
78
|
+
ROOT: <...>
|
|
79
|
+
|
|
80
|
+
Supported hypothesis: H<n> [FAULT-TYPE]: <cause>
|
|
81
|
+
|
|
82
|
+
## Proposed fix
|
|
83
|
+
|
|
84
|
+
- Direct: <from RCA Phase 5 Direct fix>
|
|
85
|
+
- Systemic (Critical only): <test/alert/process gap to close>
|
|
86
|
+
|
|
87
|
+
## Acceptance criteria
|
|
88
|
+
|
|
89
|
+
- [ ] <testable condition 1>
|
|
90
|
+
- [ ] <testable condition 2>
|
|
91
|
+
- [ ] Existing tests still pass
|
|
92
|
+
- [ ] New regression test added (if systemic fix applies)
|
|
93
|
+
|
|
94
|
+
## Evidence
|
|
95
|
+
|
|
96
|
+
- Production logs: <log snippet or path>
|
|
97
|
+
- Git blame: <commit that introduced the issue, if identified>
|
|
98
|
+
- RCA full output: <paste or link>
|
|
99
|
+
|
|
100
|
+
🤖 Filed by Ciel (debug-reasoning-rca + issue-creator)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**For feature-request:**
|
|
104
|
+
```markdown
|
|
105
|
+
## Goal
|
|
106
|
+
|
|
107
|
+
<1-sentence goal>
|
|
108
|
+
|
|
109
|
+
## Motivation
|
|
110
|
+
|
|
111
|
+
<Why this is needed now — user story, metric, constraint>
|
|
112
|
+
|
|
113
|
+
## Proposed approach
|
|
114
|
+
|
|
115
|
+
<High-level approach from evaluer-sizer if available>
|
|
116
|
+
|
|
117
|
+
## Acceptance criteria
|
|
118
|
+
|
|
119
|
+
- [ ] <testable>
|
|
120
|
+
- [ ] <testable>
|
|
121
|
+
- [ ] Documentation updated
|
|
122
|
+
- [ ] Relevant tests added
|
|
123
|
+
|
|
124
|
+
## Out of scope
|
|
125
|
+
|
|
126
|
+
- <NOT-X from quoi-framer>
|
|
127
|
+
|
|
128
|
+
🤖 Filed by Ciel
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 3. Create the issue
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
gh issue create \
|
|
135
|
+
--title "<title>" \
|
|
136
|
+
--body-file /tmp/ciel-issue-body-$$ \
|
|
137
|
+
--label "<labels>" \
|
|
138
|
+
--assignee "<assignees>"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Capture the returned URL, extract the issue number.
|
|
142
|
+
|
|
143
|
+
### 4. Emit output for downstream skills
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
[ISSUE CREATED]
|
|
147
|
+
Number: #<N>
|
|
148
|
+
URL: https://github.com/<org>/<repo>/issues/<N>
|
|
149
|
+
Title: <title>
|
|
150
|
+
Labels: <labels>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Pass `#<N>` to `branch-setup` and future `commit-writer` / `pr-opener` calls.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Guardrails
|
|
158
|
+
|
|
159
|
+
- **Never create without gh auth** — preflight must pass.
|
|
160
|
+
- **Respect existing issues** — dupe check is mandatory; don't pollute the tracker.
|
|
161
|
+
- **Don't create on forks** — check `gh repo view --json nameWithOwner` matches upstream. Otherwise ask user to confirm.
|
|
162
|
+
- **Critical label enforcement** — if Ciel depth is Critical, the issue MUST have the `critical` label (compliance audit).
|
|
163
|
+
- **Body under 65 KB** — GitHub's hard limit; truncate + link to gist if RCA evidence exceeds.
|
|
164
|
+
- **One issue per root cause** — don't bundle unrelated symptoms. If RCA found 2 distinct root causes, create 2 issues.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## When triggered
|
|
169
|
+
|
|
170
|
+
- After `debug-reasoning-rca` returns a verdict with `confidence: HIGH` or `MEDIUM`
|
|
171
|
+
- Start of a FEATURE intent task (non-trivial)
|
|
172
|
+
- Explicit user ask: "file an issue for this"
|
|
173
|
+
- Before `branch-setup` (issue number is an input)
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## How to verify
|
|
178
|
+
|
|
179
|
+
- [ ] `gh auth status` passes?
|
|
180
|
+
- [ ] Duplicate check performed? (`gh issue list --search` ran)
|
|
181
|
+
- [ ] Issue created on GitHub? (`gh issue view <N>` succeeds)
|
|
182
|
+
- [ ] Body has Problem/Root cause/Acceptance criteria sections?
|
|
183
|
+
- [ ] Labels applied (type + severity for bugs)?
|
|
184
|
+
- [ ] Issue number returned for downstream skills?
|
|
185
|
+
- [ ] Critical tasks have `critical` label?
|
|
186
|
+
|
|
187
|
+
## Anti-pattern
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
❌ RCA completes → jump straight to writing code → commit → PR → no paper trail
|
|
191
|
+
✅ RCA completes → issue-creator → branch-setup → work → pr-opener → issue-closer
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## References
|
|
197
|
+
|
|
198
|
+
- GitHub CLI — cli.github.com/manual/gh_issue_create
|
|
199
|
+
- Ciel pipeline: issue-creator → branch-setup → (FAIRE work) → pr-opener → issue-closer
|
|
200
|
+
- SOC 2 audit trail requirement for production changes
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-merger
|
|
3
|
+
description: Merges a GitHub PR safely — reads branch protection (reviews, checks, CODEOWNERS), flips draft→ready on green CI, picks squash/rebase/merge from repo config, uses `--auto`. Gated by prouver-verifier VERDICT=DONE. Hands off to issue-closer + branch-cleaner. Invoke on "merge PR" / "auto-merge" / "land this PR". Inline.
|
|
4
|
+
allowed-tools: Bash, Read
|
|
5
|
+
context: inline
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# pr-merger — Close the loop with branch-protection awareness
|
|
9
|
+
|
|
10
|
+
Opening a PR is only half the workflow. `pr-merger` owns the other half: flip draft → ready, wait for green CI + approvals, respect branch protection, pick the right merge strategy, then hand off to post-merge cleanup.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
PR_NUMBER: [from current branch via `gh pr view --json number` or explicit]
|
|
18
|
+
MERGE_STRATEGY: [squash | rebase | merge — default: read from repo settings]
|
|
19
|
+
AUTO: [true | false — default true; uses --auto to queue behind protection gates]
|
|
20
|
+
DELETE_BRANCH: [true | false — default true; deletes source branch after merge]
|
|
21
|
+
PROUVER_VERDICT: [DONE | PENDING — must be DONE to proceed]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Auto-inference sources
|
|
25
|
+
|
|
26
|
+
- **PR_NUMBER** → `gh pr view --json number --jq .number` from current branch
|
|
27
|
+
- **MERGE_STRATEGY** → `gh api repos/{owner}/{repo} --jq '.allow_squash_merge, .allow_rebase_merge, .allow_merge_commit'` — prefer squash > rebase > merge if multiple allowed. Match repo convention from last 10 merged PRs.
|
|
28
|
+
- **PROUVER_VERDICT** → output of `prouver-verifier` in same session
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Preflight
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
gh auth status 2>&1 | grep -q "Logged in" || { echo "gh not authenticated"; exit 1; }
|
|
36
|
+
|
|
37
|
+
# PR must exist and be open
|
|
38
|
+
PR_NUMBER=${PR_NUMBER:-$(gh pr view --json number --jq .number 2>/dev/null)}
|
|
39
|
+
[ -z "$PR_NUMBER" ] && { echo "No PR found for current branch"; exit 1; }
|
|
40
|
+
|
|
41
|
+
STATE=$(gh pr view "$PR_NUMBER" --json state --jq .state)
|
|
42
|
+
[ "$STATE" = "OPEN" ] || { echo "PR #$PR_NUMBER is $STATE — cannot merge"; exit 1; }
|
|
43
|
+
|
|
44
|
+
# prouver-verifier gate
|
|
45
|
+
[ "$PROUVER_VERDICT" = "DONE" ] || { echo "prouver-verifier verdict is $PROUVER_VERDICT — run it first"; exit 1; }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Process
|
|
51
|
+
|
|
52
|
+
### 1. Read branch protection rules
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
OWNER_REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner)
|
|
56
|
+
BASE=$(gh pr view "$PR_NUMBER" --json baseRefName --jq .baseRefName)
|
|
57
|
+
|
|
58
|
+
# Protection settings (may return 404 if unprotected — treat as unprotected)
|
|
59
|
+
PROTECTION=$(gh api "repos/$OWNER_REPO/branches/$BASE/protection" 2>/dev/null || echo "{}")
|
|
60
|
+
|
|
61
|
+
REQUIRED_REVIEWS=$(echo "$PROTECTION" | jq -r '.required_pull_request_reviews.required_approving_review_count // 0')
|
|
62
|
+
REQUIRED_CHECKS=$(echo "$PROTECTION" | jq -r '.required_status_checks.contexts // [] | join(",")')
|
|
63
|
+
REQUIRES_CODEOWNERS=$(echo "$PROTECTION" | jq -r '.required_pull_request_reviews.require_code_owner_reviews // false')
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Verify approvals + checks
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Approvals
|
|
70
|
+
APPROVED=$(gh pr view "$PR_NUMBER" --json reviewDecision --jq .reviewDecision)
|
|
71
|
+
if [ "$REQUIRED_REVIEWS" -gt 0 ] && [ "$APPROVED" != "APPROVED" ]; then
|
|
72
|
+
echo "PR needs approval (reviewDecision=$APPROVED, required=$REQUIRED_REVIEWS)"
|
|
73
|
+
echo "Action: request review via gh pr edit --add-reviewer @user OR wait"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Required status checks
|
|
78
|
+
CHECKS=$(gh pr view "$PR_NUMBER" --json statusCheckRollup --jq '.statusCheckRollup[] | select(.conclusion != "SUCCESS" and .conclusion != "NEUTRAL" and .conclusion != "SKIPPED") | .name')
|
|
79
|
+
if [ -n "$CHECKS" ]; then
|
|
80
|
+
echo "Failing/pending checks:"
|
|
81
|
+
echo "$CHECKS"
|
|
82
|
+
echo "Hand off to ci-watcher for retry/flaky detection"
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 3. Flip draft → ready (if still draft + CI green)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
IS_DRAFT=$(gh pr view "$PR_NUMBER" --json isDraft --jq .isDraft)
|
|
91
|
+
if [ "$IS_DRAFT" = "true" ]; then
|
|
92
|
+
echo "Flipping draft → ready (CI is green)"
|
|
93
|
+
gh pr ready "$PR_NUMBER"
|
|
94
|
+
fi
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 4. Pick merge strategy
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
case "$MERGE_STRATEGY" in
|
|
101
|
+
squash) FLAG="--squash" ;;
|
|
102
|
+
rebase) FLAG="--rebase" ;;
|
|
103
|
+
merge) FLAG="--merge" ;;
|
|
104
|
+
*) echo "Unknown strategy: $MERGE_STRATEGY"; exit 1 ;;
|
|
105
|
+
esac
|
|
106
|
+
|
|
107
|
+
# delete-branch flag
|
|
108
|
+
DELETE_FLAG=""
|
|
109
|
+
[ "$DELETE_BRANCH" = "true" ] && DELETE_FLAG="--delete-branch"
|
|
110
|
+
|
|
111
|
+
# auto flag
|
|
112
|
+
AUTO_FLAG=""
|
|
113
|
+
[ "$AUTO" = "true" ] && AUTO_FLAG="--auto"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 5. Merge
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
gh pr merge "$PR_NUMBER" $FLAG $AUTO_FLAG $DELETE_FLAG
|
|
120
|
+
MERGE_STATUS=$?
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If `--auto` is set, GitHub queues the merge. If not, the merge completes synchronously.
|
|
124
|
+
|
|
125
|
+
### 6. Emit output + hand off
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
[PR MERGED] (or [PR QUEUED] if --auto pending on checks)
|
|
129
|
+
Number: #<P>
|
|
130
|
+
Strategy: <squash|rebase|merge>
|
|
131
|
+
Branch deleted: <yes|no>
|
|
132
|
+
|
|
133
|
+
Handoff:
|
|
134
|
+
- issue-closer (if PR closes an issue — from `Closes #N` in body)
|
|
135
|
+
- branch-cleaner (local cleanup of merged branch)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Post-merge, the caller should invoke `issue-closer` and `branch-cleaner` in sequence.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Guardrails
|
|
143
|
+
|
|
144
|
+
- **prouver-verifier gate is non-negotiable** — never merge without DONE verdict. Skipping skips evidence capture.
|
|
145
|
+
- **Never merge a draft** — flip to ready first, explicitly.
|
|
146
|
+
- **Never bypass branch protection** — if protection fails, surface the reason and stop. Don't suggest disabling protection.
|
|
147
|
+
- **Match repo strategy** — a repo that only allows squash should never receive `--merge`. Read settings, don't assume.
|
|
148
|
+
- **Never `--admin`** — admin merge bypasses protection. Refuse unless user explicitly requests AND explains why.
|
|
149
|
+
- **Auto-merge requires protection** — `--auto` only works if branch protection is configured. Fall back to synchronous merge if not.
|
|
150
|
+
- **Respect `[WIP]` / `[DO NOT MERGE]` in title** — block merge, surface the marker.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## When triggered
|
|
155
|
+
|
|
156
|
+
- End of Standard pipeline after `pr-opener` + `prouver-verifier` + `ci-watcher` all return green
|
|
157
|
+
- User says: "merge this PR", "enable auto-merge", "land this"
|
|
158
|
+
- Skipped on Trivial tasks (direct push to main)
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Anti-pattern
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
❌ gh pr merge 42 --admin --merge # bypasses protection AND wrong strategy
|
|
166
|
+
✅ pr-merger reads protection, picks squash (repo convention), --auto queues behind CI
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
❌ Merge PR while draft # reviewers haven't been asked yet
|
|
171
|
+
✅ gh pr ready first, then gh pr merge
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Handoff to downstream skills
|
|
177
|
+
|
|
178
|
+
- `issue-closer` — reads `Closes #N` from PR body, posts evidence comment, closes issue
|
|
179
|
+
- `branch-cleaner` — deletes merged branch locally + prunes remote refs
|
|
180
|
+
- `changelog-updater` — if PR has `release-note` label or is on a version-bump branch
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## References
|
|
185
|
+
|
|
186
|
+
- GitHub CLI — cli.github.com/manual/gh_pr_merge
|
|
187
|
+
- Branch protection API — docs.github.com/en/rest/branches/branch-protection
|
|
188
|
+
- Merge queue — docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue
|
|
189
|
+
- Ciel pipeline: pr-opener → ci-watcher → pr-merger → issue-closer → branch-cleaner
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-opener
|
|
3
|
+
description: Opens a GitHub pull request for the current branch using `gh pr create`. Composes the body with Summary + Test plan + Closes #N, auto-links the tracked issue (Closes #N), attaches Ciel verification evidence (tests passing, CI green, RELIRE verdict). Runs after FAIRE completion, before the user asks. The final step of the automated workflow before issue-closer. Inline — deterministic `gh` command.
|
|
4
|
+
allowed-tools: Bash, Read
|
|
5
|
+
context: inline
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# pr-opener — Close the loop, link the issue
|
|
9
|
+
|
|
10
|
+
A PR without an issue link is a commit without a reason. Ciel's `pr-opener` guarantees every PR auto-closes its source issue on merge.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
ISSUE_NUMBER: [from .git/ciel-work-context written by branch-setup]
|
|
18
|
+
BRANCH: [current branch — from git rev-parse]
|
|
19
|
+
TITLE: [1-line summary — imperative, ≤ 70 chars]
|
|
20
|
+
BASE_BRANCH: [main usually, from .git/ciel-work-context]
|
|
21
|
+
DRAFT: [true|false — default false, true if CI not yet green]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Auto-inference sources
|
|
25
|
+
|
|
26
|
+
- **ISSUE_NUMBER, BRANCH, BASE_BRANCH** → read `.git/ciel-work-context`
|
|
27
|
+
- **TITLE** → derive from the latest commit message on the branch (`git log -1 --format=%s`), strip conventional-commit prefix if present
|
|
28
|
+
- **DRAFT** → true if `gh run list --branch=$BRANCH --limit=1 --json status --jq '.[0].status'` returns in_progress OR any test is failing
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Preflight
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# 1. gh auth
|
|
36
|
+
gh auth status 2>&1 | grep -q "Logged in" || { echo "gh not authenticated"; exit 1; }
|
|
37
|
+
|
|
38
|
+
# 2. Branch pushed to origin
|
|
39
|
+
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
40
|
+
git ls-remote --exit-code origin "$CURRENT" > /dev/null 2>&1 || {
|
|
41
|
+
echo "Branch not pushed — pushing now"
|
|
42
|
+
git push -u origin "$CURRENT"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# 3. Work context exists
|
|
46
|
+
[ -f .git/ciel-work-context ] || { echo "No .git/ciel-work-context — did branch-setup run?"; exit 1; }
|
|
47
|
+
|
|
48
|
+
# 4. Not already a PR open for this branch
|
|
49
|
+
gh pr list --head "$CURRENT" --state=open --json number --jq '.[0].number' | grep -q . && {
|
|
50
|
+
PR_NUM=$(gh pr list --head "$CURRENT" --state=open --json number --jq '.[0].number')
|
|
51
|
+
echo "PR already exists: #$PR_NUM — updating body instead"
|
|
52
|
+
UPDATE_MODE=true
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Process
|
|
59
|
+
|
|
60
|
+
### 1. Compose the PR body
|
|
61
|
+
|
|
62
|
+
Extract linked issue from branch name (`<type>/<N>-...` → issue #N) or `.git/ciel-work-context`.
|
|
63
|
+
|
|
64
|
+
Summarize changes from commits + diff stat: top 3 changes by impact (by lines changed or commit subject classification). Avoid exhaustive file list.
|
|
65
|
+
|
|
66
|
+
Assemble with:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
ISSUE_NUMBER: <N>
|
|
70
|
+
BRANCH: <branch>
|
|
71
|
+
COMMITS: git log origin/$BASE_BRANCH..HEAD --oneline
|
|
72
|
+
CHANGED_FILES: git diff --stat origin/$BASE_BRANCH...HEAD
|
|
73
|
+
RELIRE_VERDICT: [from critic agent if invoked]
|
|
74
|
+
CI_STATUS: gh run list --branch=<branch> --limit=1 --json conclusion
|
|
75
|
+
EVIDENCE: [prouver-verifier output if applicable]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Expected body structure (generated):
|
|
79
|
+
|
|
80
|
+
```markdown
|
|
81
|
+
## Summary
|
|
82
|
+
|
|
83
|
+
<1-3 bullets — what changed and why>
|
|
84
|
+
|
|
85
|
+
## Closes
|
|
86
|
+
|
|
87
|
+
Closes #<N>
|
|
88
|
+
|
|
89
|
+
## Changes
|
|
90
|
+
|
|
91
|
+
<git diff --stat output>
|
|
92
|
+
|
|
93
|
+
## Test plan
|
|
94
|
+
|
|
95
|
+
- [x] Unit tests pass (<N> added/modified)
|
|
96
|
+
- [x] Integration tests pass
|
|
97
|
+
- [x] Manual verification: <staging evidence from prouver-verifier>
|
|
98
|
+
- [x] No regression on existing suites
|
|
99
|
+
|
|
100
|
+
## Evidence
|
|
101
|
+
|
|
102
|
+
- Staging logs: <snippet>
|
|
103
|
+
- CI run: <URL to gh run>
|
|
104
|
+
- RELIRE verdict: <BLOCKING: none | IMPORTANT: N | MINOR: N>
|
|
105
|
+
|
|
106
|
+
🤖 Opened by Ciel (pr-opener)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 2. Create or update the PR
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
if [ -z "$UPDATE_MODE" ]; then
|
|
113
|
+
gh pr create \
|
|
114
|
+
--base "$BASE_BRANCH" \
|
|
115
|
+
--head "$CURRENT" \
|
|
116
|
+
--title "<title>" \
|
|
117
|
+
--body-file /tmp/ciel-pr-body-$$ \
|
|
118
|
+
$([ "$DRAFT" = "true" ] && echo "--draft")
|
|
119
|
+
else
|
|
120
|
+
gh pr edit "$PR_NUM" --body-file /tmp/ciel-pr-body-$$
|
|
121
|
+
fi
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 3. Emit output
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
[PR OPENED]
|
|
128
|
+
Number: #<P>
|
|
129
|
+
URL: https://github.com/<org>/<repo>/pull/<P>
|
|
130
|
+
Closes: #<N>
|
|
131
|
+
Draft: <true|false>
|
|
132
|
+
CI: <pending|running|passed|failed>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Guardrails
|
|
138
|
+
|
|
139
|
+
- **Closes #N is mandatory** — if the work came from an issue, the PR MUST close it on merge. This is what makes the workflow a closed loop.
|
|
140
|
+
- **Draft if CI red** — don't request review on a broken PR. Flip to ready only after CI green.
|
|
141
|
+
- **Body ≤ 65 KB** — GitHub limit; truncate evidence + link to gist if needed.
|
|
142
|
+
- **Push before PR** — branch must be on origin. Auto-push if not.
|
|
143
|
+
- **Respect existing PR** — if one is already open for this branch, UPDATE it, don't create a duplicate.
|
|
144
|
+
- **Never auto-merge** — opening the PR is the end of Ciel's automated work. Merge decision is the user's.
|
|
145
|
+
- **`prouver-verifier` MUST have run green before the merge command** (mirror of `skills/ciel/SKILL.md`) — applies to every merge path: `gh pr merge [--auto|--squash|--merge|--rebase]`, `git push` direct-to-default, GitHub UI "Merge" button. If pr-opener is asked to auto-merge (e.g., user passes a `--merge-when-green` intent), refuse unless `.git/ciel-prouver-verdict` exists with `verdict=PASS`.
|
|
146
|
+
- **Never `--no-verify`** — pre-push hooks run; if they fail, investigate, don't skip.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## When triggered
|
|
151
|
+
|
|
152
|
+
- End of FAIRE step when a branch was created by `branch-setup`
|
|
153
|
+
- `prouver-verifier` PROUVER step completes successfully
|
|
154
|
+
- User says "open a PR" after finishing work
|
|
155
|
+
- Skip if Trivial task (direct push to main was the intent)
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## How to verify
|
|
160
|
+
|
|
161
|
+
- [ ] `gh auth status` passes?
|
|
162
|
+
- [ ] Branch pushed to origin?
|
|
163
|
+
- [ ] `.git/ciel-work-context` exists?
|
|
164
|
+
- [ ] PR created/updated on GitHub? (`gh pr view` succeeds)
|
|
165
|
+
- [ ] `Closes #N` present in body?
|
|
166
|
+
- [ ] Body has Summary + Test plan + Evidence sections?
|
|
167
|
+
- [ ] Draft status correct? (draft if CI red, ready if green)
|
|
168
|
+
- [ ] No duplicate PR? (checked for existing open PR first)
|
|
169
|
+
|
|
170
|
+
## Handoff to issue-closer
|
|
171
|
+
|
|
172
|
+
`pr-opener` DOES NOT close the issue — `issue-closer` does that POST-merge with evidence. The PR body's `Closes #N` is a GitHub-level auto-close hook; `issue-closer` adds the structured comment with production evidence after merge lands.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## References
|
|
177
|
+
|
|
178
|
+
- GitHub CLI — cli.github.com/manual/gh_pr_create
|
|
179
|
+
- GitHub auto-close keywords — docs.github.com/en/issues/tracking-your-work-with-issues/closing-an-issue-automatically
|
|
180
|
+
- Ciel pipeline: issue-creator → branch-setup → FAIRE → pr-opener → issue-closer (post-merge)
|