@mmerterden/multi-agent-pipeline 16.23.0 → 16.24.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/CHANGELOG.md CHANGED
@@ -16,6 +16,28 @@ Internal file-layout changes that don't affect the slash-command surface are sti
16
16
 
17
17
  ## [Unreleased]
18
18
 
19
+ ## [16.24.0] - 2026-09-09
20
+
21
+ ### Added
22
+
23
+ - **A UI fix now carries its picture.** Three changed files in a diff do not tell a reviewer what was wrong, and they do not tell a tester what to look for. When `taskType` is `bugfix` and a UI file changed, the run produces a before/after pair; when the work is design (a `component` task, a Figma reference, or a UI file that did not exist before), it produces the after. The verdict comes from `taskType` plus the changed-file list, mechanically, not from the model's reading of the task - the UI-file test is per stack and written down.
24
+
25
+ **Before is the reporter's screenshot, or nothing.** Rebuilding the pre-fix state to photograph it costs a second build and a second launch on every UI bug, to recreate evidence the reporter usually attached already. So Phase 0 keeps the issue's own image attachments and that is the whole of it; no image on the ticket is a recorded gap, not a search.
26
+
27
+ **After is captured in Phase 3, not Phase 5.** Phase 5 is the natural home - the simulator is already up - and it is dropped by every `autopilot` and `--local` entry, so a capture living only there produces nothing for exactly the runs nobody watched. It happens instead right after the build+test gate goes green, which is in every mode's phase set. `capture-evidence.sh` owns the naming, cleans the status bar (two shots of one screen otherwise differ by the clock, which makes every "after" look like a change) and downscales to 1242px.
28
+
29
+ - **The flow video, in three tiers, so no repo is excluded by not having a test target.** Tier 1 runs the repo's own XCUITest/Espresso target when it can be seeded with test data - the most faithful record, and it is a test that already runs in CI. Tier 2 drives the flow with `agent_run_steps` and records with `ios_record_video` / `android_record_screen`, needing nothing but a launchable build. Tier 3 is the honest skip for a library or a backend, with the reason recorded. The flow itself comes from the ticket when someone wrote one there, and from the Phase 5 test scenarios otherwise: human-written beats generated, the same rule the before follows.
30
+
31
+ - **Where they land.** The artefacts are Jira attachments. The Phase 7 comment renders them _inside_ its existing sections rather than adding a fourth - the section order is fixed and the contract says so - with the before/after thumbnails under the work summary and the flow video under the scenario it demonstrates. The PR body gains a `visuals` section that names the filenames and the ticket, deliberately not the URLs: a Jira attachment URL is auth-gated and renders as a broken image for anyone reading the PR outside a Jira session.
32
+
33
+ - **Degrading quality is allowed; dropping the artefact is not.** Jira's ceiling is an instance setting, so it is a preference (`visualEvidence.maxAttachmentMb`, default 10). Over it, a video re-encodes to 720p and a screenshot to JPEG q80; still over, the video becomes a four-frame contact sheet that says why. Phase 6 Step 3 blocks when a required artefact is neither attached nor explained - the gate is against silence, not against an honest "the ticket carries no image".
34
+
35
+ - **`smoke-visual-evidence.sh`** - 32 checks, most of them about stated absence being as required as stated presence: both scripts refuse bad input rather than guessing, the size ladder never returns an empty path, all four phases act, both renderers know where pictures go, the schemas declare the fields, and no ref re-implements the attachment POST.
36
+
37
+ ### Changed
38
+
39
+ - **One Jira uploader instead of two.** `generate-issue.md` carried its own attachment `curl`; visual evidence would have been the second copy, and two copies is two places for `X-Atlassian-Token: no-check` to go missing - which fails as a 403 that reads like an auth problem. Both now call `jira-attach.sh`, which resolves host and token from prefs, keeps the token out of argv, and prints `<filename>\t<url>` per file.
40
+
19
41
  ## [16.23.0] - 2026-09-09
20
42
 
21
43
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "16.23.0",
3
+ "version": "16.24.0",
4
4
  "description": "8-phase AI development pipeline with full orchestration on Claude Code, Copilot CLI and Codex CLI. Analysis, planning, TDD, CLI-aware parallel review with consensus surfacing + Fable triage, default-FAIL evidence gates, secret + intent guards, per-phase cost ledger, persistent learnings memory, wiki generation, commit automation. Token-preserving uninstall.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -20,6 +20,13 @@ Every Jira comment posted by this adapter follows the same section order. Sectio
20
20
 
21
21
  **`summary`** - 2-5 sentences in `outputLanguage`. What changed, why, and the user-visible impact. No "we", no marketing tone. Past tense (the work is done at the time the comment goes up).
22
22
 
23
+ **Visual evidence inside these two sections.** When `state.visualEvidence` carries artefacts, they render INSIDE `summary` and `test_scenarios` - never as a fourth section, which the fixed section order forbids. Upload first (`jira-attach.sh <issue> <file>...`), then reference by the returned filename:
24
+
25
+ - `summary`, after its sentences: one line naming the pair in `outputLanguage` (`Düzeltme öncesi / Düzeltme sonrası`), then the thumbnails on the next line - `!<file>-before.png|thumbnail! !<file>-after.png|thumbnail!`.
26
+ - `test_scenarios`, under the scenario the recording demonstrates: `!<file>-flow.mp4!` plus one line stating the tier used.
27
+
28
+ A `gaps[]` entry prints its reason on the line where the artefact would have been (`Düzeltme öncesi: ticket'ta görsel yok`). Never an empty thumbnail, never a silent omission. Contract: `$HOME/.claude/multi-agent-refs/features/visual-evidence.md`.
29
+
23
30
  **`test_scenarios`** - Given/When/Then numbered list. One scenario per acceptance criterion. The heading and scenario text are rendered in `outputLanguage` at write-time; the template itself (this file) shows the English skeleton:
24
31
 
25
32
  ```markdown
@@ -14,9 +14,10 @@ The PR description targets code reviewers - it stays technical. Every adapter
14
14
  | 2 | `changes` | `## Değişiklikler` | `## Changes` | always |
15
15
  | 3 | `architecture` | `## Mimari Kararlar` | `## Architecture Decisions` | when a non-trivial design choice was made |
16
16
  | 4 | `verification` | `## Doğrulama` | `## Verification` | always |
17
- | 5 | `risk` | `## Risk ve Güvenlik` | `## Risk and Security` | when `state.diffRisk.signals` carries a high-stakes signal (`security_path`, `migration`, `public_api`, `no_test_change`, `test_lines_removed`) |
18
- | 6 | `dependencies` | `## Bağımlılıklar` | `## Dependencies` | when deps added/removed/bumped |
19
- | 7 | `related` | `## İlgili` | `## Related` | always (Jira/issue ref; never `Closes/Fixes`) |
17
+ | 5 | `visuals` | `## Görsel Kanıt` | `## Visual Evidence` | when `state.visualEvidence.required` |
18
+ | 6 | `risk` | `## Risk ve Güvenlik` | `## Risk and Security` | when `state.diffRisk.signals` carries a high-stakes signal (`security_path`, `migration`, `public_api`, `no_test_change`, `test_lines_removed`) |
19
+ | 7 | `dependencies` | `## Bağımlılıklar` | `## Dependencies` | when deps added/removed/bumped |
20
+ | 8 | `related` | `## İlgili` | `## Related` | always (Jira/issue ref; never `Closes/Fixes`) |
20
21
 
21
22
  ### Section content rules
22
23
 
@@ -62,6 +63,18 @@ Multi-repo PRs (one PR per repo) emit verification commands for that repo's stac
62
63
  - Rollback: feature flag <name> | git revert <sha> | none, and why
63
64
  ```
64
65
 
66
+ **`visuals`** - only when `state.visualEvidence.required`. The images live on the Jira issue as attachments; this section exists so a reviewer opening the PR knows they are there and what each one shows. Filenames, not raw URLs - a Jira attachment URL is auth-gated and renders as a broken image for anyone reading the PR outside a Jira session.
67
+
68
+ ```markdown
69
+ ## Visual Evidence
70
+
71
+ - Before: `<before-filename>` (attached to PROJ-XXXXX)
72
+ - After: `<after-filename>` (attached to PROJ-XXXXX)
73
+ - Flow video: `<flow-filename>`, tier <N> (attached to PROJ-XXXXX)
74
+ ```
75
+
76
+ Every `state.visualEvidence.gaps[]` entry becomes its own line with the reason instead of a filename (`- Before: none - the ticket carries no image attachment`). Phase 6 Step 3 blocks on a required artefact that is neither listed nor explained. Contract: `$HOME/.claude/multi-agent-refs/features/visual-evidence.md`.
77
+
65
78
  **`dependencies`** - only when `Package.swift` / `Podfile` / `build.gradle` / `package.json` changed. Each entry: `package@old → new - reason`.
66
79
 
67
80
  **`related`** - flat list, plain text. Examples:
@@ -0,0 +1,172 @@
1
+ # Visual evidence - before/after screenshots and the UI flow video
2
+
3
+ A UI fix that reads as three changed files in a diff is not reviewable. The
4
+ reviewer cannot see what was wrong, and the tester cannot see what to look for.
5
+ This contract makes the pipeline carry the picture: the state the reporter saw,
6
+ the state the fix produces, and where possible a recording of the flow running.
7
+
8
+ The artefacts live as **Jira attachments** and are referenced from two places -
9
+ the Phase 7 Jira comment, where the picture belongs next to the work summary and
10
+ the test scenarios, and the PR body, which tells the reviewer they exist.
11
+
12
+ Consumers: Phase 3 (capture), Phase 5 (video, preferred host), Phase 6 (blocker),
13
+ `channels/jira.md` and `channels/pr.md` (render). Gate: `smoke-visual-evidence.sh`.
14
+
15
+ ## 1. When it is required
16
+
17
+ Decided mechanically from `taskType` plus the changed-file list, never from the
18
+ model's reading of the task. A file counts as UI by stack:
19
+
20
+ | Stack | UI file test |
21
+ |---|---|
22
+ | iOS | `.swift` declaring `: View`, `: ViewController`, or under a `Views/` path |
23
+ | Android | `.kt` with `@Composable`, or declaring `: Activity` / `: Fragment` |
24
+ | Web | `.tsx` / `.jsx` / `.vue` / `.svelte` |
25
+
26
+ | Case | Before | After | Video |
27
+ |---|---|---|---|
28
+ | `taskType` is `bugfix` AND a UI file changed | required | required | when a tier allows |
29
+ | Design work: `taskType` is `component`, or Figma was referenced, or a UI file was **added** | not applicable | required | when a tier allows |
30
+ | Anything else | - | - | - |
31
+
32
+ `state.visualEvidence.required` records the verdict and which rule produced it.
33
+ Nothing about this section is optional-by-omission: when it is required and an
34
+ artefact is absent, the absence is written down with its reason (section 5).
35
+
36
+ ## 2. Before - the reporter's screenshot, or nothing
37
+
38
+ **The pipeline does not build the old state to photograph it.** Reproducing a
39
+ pre-fix screen costs a second build and a second launch on every UI bug, to
40
+ recreate evidence the reporter has usually already attached.
41
+
42
+ So: Phase 0 already fetches the issue. Any image attachment on it (`.png`,
43
+ `.jpg`, `.jpeg`, `.gif`, `.heic`) is downloaded to `$WORKTREE/.pipeline/evidence/`
44
+ and recorded as `state.visualEvidence.before[]`. More than one is kept - a bug
45
+ reported on two platforms has two.
46
+
47
+ No image on the ticket means no "before". Record the gap
48
+ (`before_missing: "ticket carries no image attachment"`) and continue. The
49
+ section still renders, saying so.
50
+
51
+ ## 3. After - Phase 3, not Phase 5
52
+
53
+ Phase 5 is the natural home: the simulator is already up. It is also **dropped by
54
+ every `autopilot` and `--local` entry** (`phase-5-test.md` TLDR), so a capture
55
+ that lives only there produces nothing for unattended runs - which are exactly
56
+ the runs where nobody watched the screen.
57
+
58
+ The capture therefore happens in **Phase 3, after the build+test gate passes**,
59
+ which is in every mode's phase set. Phase 5 may add richer evidence on top; it is
60
+ never the only source.
61
+
62
+ ```bash
63
+ bash $HOME/.claude/scripts/capture-evidence.sh after \
64
+ --task "$TASK_ID" --platform "$PLATFORM" --label "<screen-slug>"
65
+ ```
66
+
67
+ The script boots the device if needed, launches the built app, cleans the status
68
+ bar (`ios_status_bar preset:clean` / the Android equivalent) so the frame carries
69
+ no clock, carrier or battery noise, captures at device resolution, downscales to
70
+ at most 1242px wide, and writes
71
+ `$WORKTREE/.pipeline/evidence/<TASK_ID>-<label>-after.png`.
72
+
73
+ A clean status bar is not cosmetic: without it two captures of the same screen
74
+ differ by the clock, which makes every "after" look like a change.
75
+
76
+ ## 4. Video - three tiers, resolved once per repo
77
+
78
+ The flow source, in order: a UI test flow written on the ticket wins; otherwise
79
+ the Phase 5 test scenarios are the flow. Human-written beats generated, the same
80
+ rule the "before" follows.
81
+
82
+ The tier is probed once and stored in `state.visualEvidence.videoTier`:
83
+
84
+ | Tier | Condition | Mechanism |
85
+ |---|---|---|
86
+ | 1 | The repo has a UI test target (XCUITest / Espresso) **and** it can be seeded with test data | Run that test, record the screen for its duration. Most faithful, and it is a test that already runs in CI |
87
+ | 2 | A runnable build exists | Drive the flow with `mcp__multi-agent-toolkit__agent_run_steps` and record with `ios_record_video` / `android_record_screen`. **No test target needed** |
88
+ | 3 | No runnable build (library / SPM package / backend) | Skip, with the reason recorded |
89
+
90
+ Tier 2 is why "can every repo do this" answers yes in practice: any app that can
91
+ be launched can be driven. A repo without a UI test target loses fidelity, not
92
+ the recording.
93
+
94
+ Preferred host is **Phase 5** - the device is already up and a human is present
95
+ to confirm the flow is the right one. In a mode without Phase 5, tier 2 runs at
96
+ the end of Phase 3 instead. Tier 1 always runs where the test runs.
97
+
98
+ Duration is capped by `visualEvidence.maxVideoSeconds` (default 60), read via
99
+ `capture-evidence.sh limits` so the number lives in one place rather than in two
100
+ documents. A flow that needs longer is not a review artefact, it is a debugging
101
+ session.
102
+
103
+ `visualEvidence.enabled` turns the whole feature off - capture, upload, both
104
+ render sections and the Phase 6 blocker with it.
105
+
106
+ ## 5. Size, and what happens when it does not fit
107
+
108
+ Jira's attachment ceiling is an instance setting, so it is a preference:
109
+ `visualEvidence.maxAttachmentMb` (default `10`).
110
+
111
+ Order of attempts, each one recorded:
112
+
113
+ 1. Upload as captured.
114
+ 2. On `413` or a local size overrun: re-encode. Video drops to 720p and a lower
115
+ bitrate; PNG converts to JPEG at quality 80. **Reducing quality is allowed;
116
+ dropping the artefact is not.**
117
+ 3. Still over: replace the video with a four-frame contact sheet (start, two
118
+ midpoints, end) as a single PNG, and say in the caption that the recording
119
+ exceeded the limit.
120
+
121
+ Never silently attach nothing.
122
+
123
+ ## 6. Rendering
124
+
125
+ ### Jira comment (`channels/jira.md`)
126
+
127
+ The comment's section order is fixed and nothing may be inserted between the
128
+ three sections. The evidence goes **inside** two of them:
129
+
130
+ - `summary` - after the summary sentences, the before/after pair as a Jira wiki
131
+ thumbnail row: `!<TASK>-<label>-before.png|thumbnail! !<TASK>-<label>-after.png|thumbnail!`
132
+ preceded by one line naming which is which in `outputLanguage`
133
+ (`Düzeltme öncesi / Düzeltme sonrası`).
134
+ - `test_scenarios` - the flow video attached under the scenario it demonstrates:
135
+ `!<TASK>-flow.mp4!`, one line stating the tier used.
136
+
137
+ Missing artefacts print their reason on the same line, never an empty frame.
138
+
139
+ ### PR body (`channels/pr.md`)
140
+
141
+ A `visuals` section whose job is to tell the reviewer the evidence exists and
142
+ where it lives - the images themselves stay on the ticket:
143
+
144
+ ```markdown
145
+ ## Görsel Kanıt
146
+
147
+ - Düzeltme öncesi: <before-filename> (PROJ-123 ekinde)
148
+ - Düzeltme sonrası: <after-filename> (PROJ-123 ekinde)
149
+ - Akış videosu: <flow-filename>, tier <N> (PROJ-123 ekinde)
150
+ ```
151
+
152
+ ## 7. Blocker
153
+
154
+ When section 1 says required and `state.visualEvidence` carries neither an
155
+ artefact nor a recorded reason for its absence, **Phase 6 Step 3 blocks** - the
156
+ same shape as the `risk` section blocker. A recorded reason is enough to pass:
157
+ the gate is against silence, not against an honest "no image on the ticket".
158
+
159
+ ## 8. State
160
+
161
+ ```json
162
+ "visualEvidence": {
163
+ "required": true,
164
+ "requiredBy": "bugfix + ui-file-changed",
165
+ "platform": "ios",
166
+ "before": [{"file": "...", "source": "ticket", "jiraFilename": "...", "url": "..."}],
167
+ "after": [{"file": "...", "capturedAt": "phase-3", "jiraFilename": "...", "url": "..."}],
168
+ "videoTier": 2,
169
+ "video": {"file": "...", "seconds": 41, "jiraFilename": "...", "url": "..."},
170
+ "gaps": [{"what": "before", "reason": "ticket carries no image attachment"}]
171
+ }
172
+ ```
@@ -241,11 +241,11 @@ curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application
241
241
  ```
242
242
  4. **Screenshot / image attachments** (only when opted in during preview - Figma render and/or user-pasted images):
243
243
  ```bash
244
- curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "X-Atlassian-Token: no-check" \
245
- -F "file=@/tmp/generate-issue-$$-figma.png" \
246
- "https://$ACCOUNT_JIRA_HOST/rest/api/2/issue/${NEW_KEY}/attachments"
244
+ bash "$HOME/.claude/scripts/jira-attach.sh" "$NEW_KEY" /tmp/generate-issue-$$-figma.png
247
245
  ```
248
246
 
247
+ One uploader, shared with visual evidence: two copies of this call is two places for `X-Atlassian-Token: no-check` to go missing, which fails as a 403 that reads like an auth problem. It prints `<filename>\t<url>` per file.
248
+
249
249
  ### [12/12] Report
250
250
 
251
251
  ```
@@ -93,6 +93,8 @@ Probe order:
93
93
  1. **Tier 1 (Figma MCP)**: check the host serves `mcp__claude_ai_Figma__*` before probing. Absent → set `state.figmaAccess.tier1Unavailable = "host"` and fall through to Tier 2 with no probe, no re-auth retry, no MCP-token question. Present → probe `get_metadata(fileKey, nodeId)` on the first frame; on auth failure run `authenticate` + `complete_authentication` and retry once, and only a *second* failure raises the recreate-or-continue question. Success → `state.figmaAccess.tier = 1`.
94
94
  2. **Tier 2 (Figma REST)**: when Tier 1 fails, resolve the PAT via `~/.claude/lib/credential-store.sh get <logical-key>` where `<logical-key>` = `prefs.global.keychainMapping.figma`. Probe `GET https://api.figma.com/v1/files/{fileKey}/nodes?ids={nodeId}` with header `X-Figma-Token: $TOKEN`. HTTP 200 → `state.figmaAccess.tier = 2`. Token missing / 401 / 403 → fall through.
95
95
  3. **Tier 3 (User-attached screenshot)**: when Tiers 1 + 2 both fail, scan the task payload for inline screenshots or attachments. Present → `state.figmaAccess.tier = 3` and `state.figmaAccess.reviewBlocking = true` (Phase 4 enforces this).
96
+
97
+ Save the issue's image attachments to `$WORKTREE/.pipeline/evidence/` as `state.visualEvidence.before[]`: pre-fix evidence, never re-photographed, and none present is a recorded gap rather than a search. See `$HOME/.claude/multi-agent-refs/features/visual-evidence.md`.
96
98
  4. **Halt**: all three tiers fail → emit a single AskUserQuestion asking the user how to proceed (provide PAT, paste a screenshot, abort). Never proceed with text-derived guesses.
97
99
 
98
100
  Record the cause, not just the downshift. `tier1Unavailable = "host"` means the tier never existed here - routine on Copilot and Codex, where the installer registers only `multi-agent-toolkit`. `"auth"` means it existed and the credential failed, which on Claude Code points at a dead `figma_mcp` token worth surfacing in Phase 7. Conflating them costs two wasted MCP round trips and a question the user cannot act on. On those two hosts a mapped `figma` PAT is the primary path, not a fallback.
@@ -234,6 +234,10 @@ Gated by `prefs.global.devCritic.enabled` (default: `false`). When enabled, afte
234
234
 
235
235
  ---
236
236
 
237
+ #### Step 3.55 - Visual evidence capture (UI changes only)
238
+
239
+ When `state.visualEvidence.required`, capture the fixed state with the build that just went green: `capture-evidence.sh after --task "$TASK_ID" --platform "$PLATFORM" --label <slug>`. Here, not Phase 5, which every autopilot and `--local` entry drops. Exit 4 is a gap, not a failure. See `$HOME/.claude/multi-agent-refs/features/visual-evidence.md`.
240
+
237
241
  #### Step 3.6 - Code-simplifier pass (required diff shrink, before Phase 4 handoff)
238
242
 
239
243
  After the build/test green step and BEFORE Phase 4 handoff, run one diff-shrink round (bloated diffs waste Phase 4 reviewer tokens and unfocus the PR).
@@ -138,6 +138,7 @@ Before or during user testing, run device-level audits via Bash if user requests
138
138
 
139
139
  | Check | When | Command |
140
140
  | ------------------- | ----------------- | ----------------------------------------- |
141
+ | UI flow video | `state.visualEvidence.required` | 3 tiers, cap from `capture-evidence.sh limits` (`visualEvidence.maxVideoSeconds`) - `$HOME/.claude/multi-agent-refs/features/visual-evidence.md` |
141
142
  | Accessibility audit | UI changes | `mcp__multi-agent-toolkit__{ios,android}_accessibility_audit` |
142
143
  | Biometric test | Auth flow changes | ios: `mcp__multi-agent-toolkit__ios_biometric` (android: manual) |
143
144
  | Launch time | Perf-sensitive changes | ios: app-launch instrument · android: `mcp__multi-agent-toolkit__android_launch_time` |
@@ -136,7 +136,7 @@ Branch **deterministically**, no implicit fallback. Read `agent-state.json` and
136
136
 
137
137
  Generate a structured PR description based on task type. The PR body targets **code reviewers** - it should be technical: what changed, why, architecture decisions, how to verify.
138
138
 
139
- Two inputs are read from state and the worktree before writing, not recalled from the conversation: `$WORKTREE/.pipeline/scope-check.json` (Phase 3 Step 3.7) supplies the `## Changes` bullets from `files[].reason` and the "Follow-ups not done in this PR" list under `## Related` from `notDone[]`; `state.diffRisk.signals` (Phase 4 Step 1.75) decides whether the conditional `## Risk and Security` section is required. When a high-stakes signal is present and the section is missing, this step blocks until it is written; a placeholder answer ("TBD") counts as missing.
139
+ Two inputs are read from state and the worktree before writing, not recalled from the conversation: `$WORKTREE/.pipeline/scope-check.json` (Phase 3 Step 3.7) supplies the `## Changes` bullets from `files[].reason` and the "Follow-ups not done in this PR" list under `## Related` from `notDone[]`; `state.diffRisk.signals` (Phase 4 Step 1.75) decides whether the conditional `## Risk and Security` section is required. When a high-stakes signal is present and the section is missing, this step blocks until it is written; a placeholder answer ("TBD") counts as missing. `state.visualEvidence.required` blocks the same way: every required artefact is either attached or carries a recorded reason in `gaps[]` - the gate is against silence, not against an honest "no image on the ticket".
140
140
 
141
141
  **required**: Run all generated text (PR body, commit message) through the `humanizer` skill before posting. This removes AI-generated patterns (inflated language, filler phrases, repetitive structure) and makes the output sound like a developer wrote it.
142
142