@event4u/agent-config 1.38.0 → 1.40.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 (56) hide show
  1. package/.agent-src/commands/onboard.md +131 -50
  2. package/.agent-src/commands/orchestrate.md +123 -0
  3. package/.agent-src/commands/sync-gitignore/fix.md +135 -0
  4. package/.agent-src/commands/sync-gitignore.md +31 -5
  5. package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +30 -2
  6. package/.agent-src/skills/subagent-orchestration/SKILL.md +9 -0
  7. package/.agent-src/skills/using-git-worktrees/SKILL.md +25 -0
  8. package/.agent-src/templates/agent-settings.md +9 -0
  9. package/.agent-src/templates/agents/agent-project-settings.example.yml +9 -2
  10. package/.agent-src/templates/scripts/work_engine/_lib/__init__.py +7 -0
  11. package/.agent-src/templates/scripts/work_engine/_lib/agent_settings.py +168 -0
  12. package/.agent-src/templates/scripts/work_engine/hooks/settings.py +18 -19
  13. package/.agent-src/templates/scripts/work_engine/orchestration.py +168 -0
  14. package/.claude-plugin/marketplace.json +3 -1
  15. package/AGENTS.md +4 -4
  16. package/CHANGELOG.md +76 -0
  17. package/README.md +17 -6
  18. package/bin/install.php +13 -6
  19. package/config/agent-settings.template.yml +21 -0
  20. package/docs/DISTRIBUTION_CHECKLIST.md +169 -0
  21. package/docs/architecture.md +1 -1
  22. package/docs/catalog.md +3 -2
  23. package/docs/contracts/audit-log-v1.md +142 -0
  24. package/docs/contracts/command-clusters.md +2 -0
  25. package/docs/contracts/file-ownership-matrix.json +20 -0
  26. package/docs/contracts/orchestration-dsl-v1.md +152 -0
  27. package/docs/customization.md +45 -0
  28. package/docs/getting-started.md +1 -1
  29. package/docs/guidelines/agent-infra/layered-settings.md +54 -17
  30. package/docs/installation.md +132 -0
  31. package/docs/setup/mcp-client-config.md +152 -0
  32. package/docs/setup/mcp-cloud-endpoints.md +16 -0
  33. package/docs/setup/per-ide/aider.md +48 -0
  34. package/docs/setup/per-ide/claude-code.md +108 -0
  35. package/docs/setup/per-ide/claude-desktop.md +148 -0
  36. package/docs/setup/per-ide/cline.md +43 -0
  37. package/docs/setup/per-ide/codex.md +46 -0
  38. package/docs/setup/per-ide/copilot.md +80 -0
  39. package/docs/setup/per-ide/cursor.md +125 -0
  40. package/docs/setup/per-ide/gemini-cli.md +45 -0
  41. package/docs/setup/per-ide/windsurf.md +120 -0
  42. package/package.json +1 -1
  43. package/scripts/_lib/agent_settings.py +168 -0
  44. package/scripts/compress.py +153 -1
  45. package/scripts/extract_audit_patterns.py +202 -0
  46. package/scripts/install +156 -1
  47. package/scripts/install.py +270 -10
  48. package/scripts/install.sh +52 -7
  49. package/scripts/lint_orchestration_dsl.py +214 -0
  50. package/scripts/skill_linter.py +9 -0
  51. package/scripts/sync_gitignore.py +56 -1
  52. package/templates/claude_desktop_config.json.template +21 -0
  53. package/templates/cursor-rule.mdc.j2 +7 -0
  54. package/templates/global-install-manifest.yml +91 -0
  55. package/templates/marketing-copy.yml +64 -0
  56. package/templates/windsurf-rule.md.j2 +7 -0
@@ -12,35 +12,68 @@ suggestion:
12
12
 
13
13
  # /onboard
14
14
 
15
- Centralized first-run flow. Bundles what used to be scattered "ask once"
16
- prompts (user_name, IDE, rtk install, cost profile, learning loop) into a
17
- single interactive setup. Ends by setting `onboarding.onboarded: true` in
18
- `.agent-settings.yml`.
15
+ Centralized first-run flow. Bundles scattered "ask once" prompts (user_name,
16
+ IDE, rtk install, cost profile, learning loop) into one interactive setup.
17
+ Ends by setting `onboarding.onboarded: true` in `.agent-settings.yml`.
19
18
 
20
- Triggered by the [`onboarding-gate`](../rules/onboarding-gate.md) rule when
21
- `onboarding.onboarded` is `false` or by the user explicitly re-running it.
19
+ Triggered by [`onboarding-gate`](../rules/onboarding-gate.md) when
20
+ `onboarding.onboarded` is `false`, or by explicit re-run.
22
21
 
23
22
  ## When NOT to use
24
23
 
25
24
  - Change cost profile only → [`/set-cost-profile`](set-cost-profile.md).
26
- - Single-value edit → ask the agent to change it, or edit
27
- `.agent-settings.yml` directly. The agent follows the merge rules in
28
- [`layered-settings`](../docs/guidelines/agent-infra/layered-settings.md).
25
+ - Single-value edit → ask agent to change it, or edit `.agent-settings.yml`
26
+ directly per [`layered-settings`](../docs/guidelines/agent-infra/layered-settings.md).
29
27
 
30
28
  ## Preconditions
31
29
 
32
- `.agent-settings.yml` exists. If missing, tell the user to run
33
- `scripts/install` (or `python3 scripts/install.py`) first and stop — this
34
- command assumes the file and its template-derived defaults are in place.
30
+ `.agent-settings.yml` exists. If missing, tell user to run `scripts/install`
31
+ (or `python3 scripts/install.py`) first and stop — command assumes file +
32
+ template defaults are in place.
35
33
 
36
34
  ## Steps
37
35
 
38
36
  ### 1. Greet and set expectations
39
37
 
40
- Keep it short. One line explaining this is the one-time setup, six
41
- questions, one at a time, following the iron law (`user-interaction`).
38
+ One line: one-time setup, six questions, one at a time (iron law from
39
+ `user-interaction`).
42
40
 
43
- ### 2. Capture `personal.user_name`
41
+ ### 2. Offer user-global cross-project defaults
42
+
43
+ Detect whether `~/.config/agent-config/agent-settings.yml` exists. Path is
44
+ XDG-style, matches existing `~/.config/agent-config/` dir used for
45
+ `anthropic.key`, `openai.key`, `council-spend.jsonl`.
46
+
47
+ - **File exists** → skip step entirely. Re-onboarding never overwrites
48
+ user-global file silently.
49
+ - **File missing AND first-time setup heuristic** — heuristic for "first
50
+ machine setup": no other `.agent-settings.yml` in any sibling project on
51
+ disk. Conservative shell probe:
52
+ `find $(dirname "$PWD") -maxdepth 3 -name .agent-settings.yml 2>/dev/null | grep -v "^$PWD/" | head -1`
53
+ → non-empty → developer done this before, **skip**.
54
+ → empty → first-time setup, ask:
55
+
56
+ ```
57
+ > A user-global config at ~/.config/agent-config/agent-settings.yml lets
58
+ > you carry your DX-comfort defaults (name, IDE, autonomy, cost profile,
59
+ > communication style) across every project that uses event4u/agent-config.
60
+ >
61
+ > Project-local .agent-settings.yml always wins. Only six keys are
62
+ > mergeable from the user-global file:
63
+ > name · ide · cost_profile · personal.bot_icon · personal.autonomy · caveman.speak_scope
64
+ >
65
+ > 1. Yes — create it after this onboarding finishes
66
+ > 2. No — keep settings project-local only
67
+ ```
68
+
69
+ If user picks `1`, **defer write** to tail step (see step 9). Capture choice
70
+ in working memory only; do **not** create file here. File gets written
71
+ **after** project-local values are confirmed, so initial values mirror
72
+ what developer just chose for this project.
73
+
74
+ If user picks `2`, set working-memory flag to skip step 9.
75
+
76
+ ### 3. Capture `personal.user_name`
44
77
 
45
78
  Skip if already set (non-empty). Otherwise:
46
79
 
@@ -51,11 +84,11 @@ Skip if already set (non-empty). Otherwise:
51
84
  > 2. Skip — stay anonymous
52
85
  ```
53
86
 
54
- Free-text answer → write to `personal.user_name`. `2` → leave empty.
87
+ Free-text → write to `personal.user_name`. `2` → leave empty.
55
88
 
56
- ### 3. Capture `personal.ide` (with auto-detect)
89
+ ### 4. Capture `personal.ide` (with auto-detect)
57
90
 
58
- Skip if already set. Otherwise auto-detect first:
91
+ Skip if set. Otherwise auto-detect first:
59
92
 
60
93
  ```bash
61
94
  ps aux | grep -iE '(Visual Studio Code|Code Helper|phpstorm|cursor)' | grep -v grep
@@ -73,13 +106,13 @@ ps aux | grep -iE '(Visual Studio Code|Code Helper|phpstorm|cursor)' | grep -v g
73
106
  > 4. Skip — I'll configure it later
74
107
  ```
75
108
 
76
- If IDE is set, also ask about `personal.open_edited_files` (`true`/`false`).
109
+ If IDE set, also ask `personal.open_edited_files` (`true`/`false`).
77
110
 
78
- ### 4. Capture `personal.pr_comment_bot_icon`
111
+ ### 5. Capture `personal.pr_comment_bot_icon`
79
112
 
80
- Personal preference — each developer decides how their own PR replies
81
- should look. Skip only if the user has already set a non-default value
82
- deliberately (agent can't tell, so always ask on first run):
113
+ Personal preference — each developer decides how own PR replies look. Skip
114
+ only if user already set non-default deliberately (agent can't tell, so
115
+ always ask on first run):
83
116
 
84
117
  ```
85
118
  > When I reply to PR review comments on your behalf, should I prefix each
@@ -91,7 +124,7 @@ deliberately (agent can't tell, so always ask on first run):
91
124
 
92
125
  `1` → write `personal.pr_comment_bot_icon: true`. `2` → leave `false`.
93
126
 
94
- ### 5. Detect `personal.rtk_installed`
127
+ ### 6. Detect `personal.rtk_installed`
95
128
 
96
129
  Silent `which rtk`.
97
130
 
@@ -108,16 +141,17 @@ Silent `which rtk`.
108
141
  ```
109
142
 
110
143
  `1` or `2` → run install, on success set `rtk_installed: true` and apply
111
- rtk post-install steps (telemetry off, init --global) per the
112
- [`rtk-output-filtering`](../skills/rtk-output-filtering/SKILL.md) skill.
113
- `3` → leave `rtk_installed: false` and move on. No "ask again tomorrow"
114
- logic — `/onboard` is one-shot.
144
+ rtk post-install steps (telemetry off, init --global) per
145
+ [`rtk-output-filtering`](../skills/rtk-output-filtering/SKILL.md).
146
+ `3` → leave `rtk_installed: false`, move on. No "ask again tomorrow"
147
+ `/onboard` is one-shot.
148
+
115
149
 
116
- ### 6. Confirm `cost_profile` and learning loop
150
+ ### 7. Confirm `cost_profile` and learning loop
117
151
 
118
152
  Read current `cost_profile` and `pipelines.skill_improvement` values.
119
- Present them plainly (they already have sensible defaults from the
120
- template — `minimal` + `skill_improvement: true`):
153
+ Present plainly (sensible defaults from template — `minimal` +
154
+ `skill_improvement: true`):
121
155
 
122
156
  ```
123
157
  > Cost profile: {current} (minimal by default — includes the learning loop)
@@ -128,16 +162,54 @@ template — `minimal` + `skill_improvement: true`):
128
162
  > 3. Disable learning loop — sets pipelines.skill_improvement=false
129
163
  ```
130
164
 
131
- `2` → defer to `/set-cost-profile` and return here. `3` → flip the toggle.
165
+ `2` → defer to `/set-cost-profile` and return here. `3` → flip toggle.
132
166
 
133
- ### 7. Mark onboarded
167
+ ### 8. Mark onboarded
134
168
 
135
- Write `onboarding.onboarded: true` to `.agent-settings.yml` using the
169
+ Write `onboarding.onboarded: true` to `.agent-settings.yml` using
136
170
  section-aware merge rules from
137
171
  [`layered-settings`](../docs/guidelines/agent-infra/layered-settings.md#section-aware-merge-rules)
138
- (preserve comments, key order, touch only the changed fields).
172
+ (preserve comments, key order, touch only changed fields).
173
+
174
+ ### 9. Write user-global file (only if opted in at step 2)
175
+
176
+ Skip unless step 2 captured explicit "yes". Re-confirm intent in one line —
177
+ never silent-write a file outside project tree:
178
+
179
+ ```
180
+ > Writing ~/.config/agent-config/agent-settings.yml with the six
181
+ > mergeable keys mirrored from this project's choices:
182
+ >
183
+ > name: {personal.user_name or ""}
184
+ > ide: {personal.ide or ""}
185
+ > cost_profile: {cost_profile}
186
+ > personal.bot_icon: {personal.pr_comment_bot_icon}
187
+ > personal.autonomy: {personal.autonomy or "ask"}
188
+ > caveman.speak_scope: {caveman.speak_scope or "prose_only"}
189
+ >
190
+ > 1. Yes, write it
191
+ > 2. Cancel — keep settings project-local only
192
+ ```
193
+
194
+ `1` → ensure `~/.config/agent-config/` exists (`mkdir -p`, mode `0700`),
195
+ then write file with mode `0600`. Schema is **flat-or-nested YAML keyed on
196
+ dotted paths** in whitelist documented in
197
+ [`scripts/_lib/agent_settings.py`](../scripts/_lib/agent_settings.py).
198
+ Use same section-aware merge rules from
199
+ [`layered-settings`](../docs/guidelines/agent-infra/layered-settings.md#section-aware-merge-rules)
200
+ **only if file unexpectedly already exists** between step 2 and this step
201
+ (race condition); otherwise create from scratch with exact six keys above
202
+ and a one-line file header comment:
203
+
204
+ ```yaml
205
+ # event4u/agent-config — user-global DX-comfort defaults
206
+ # Whitelist: name · ide · cost_profile · personal.bot_icon · personal.autonomy · caveman.speak_scope
207
+ # Project-local .agent-settings.yml always wins. See docs/customization.md.
208
+ ```
209
+
210
+ `2` → no write, no error, no second ask. Move on.
139
211
 
140
- ### 8. Summary
212
+ ### 10. Summary
141
213
 
142
214
  Echo what was captured, in one block:
143
215
 
@@ -152,18 +224,19 @@ Echo what was captured, in one block:
152
224
  cost_profile: {value}
153
225
  pipelines.skill_improvement: {value}
154
226
  onboarding.onboarded: true
227
+ user-global: {"written" if step 9 wrote · "—" otherwise}
155
228
 
156
229
  You can re-run this with /onboard anytime, or edit .agent-settings.yml
157
230
  directly — the agent follows the merge rules in `layered-settings` when
158
231
  you ask it to change a value.
159
232
  ```
160
233
 
161
- ### 9. Maintainer-only feature pointer
234
+ ### 11. Maintainer-only feature pointer
162
235
 
163
- Print a one-screen hint after the summary — no question, no prompt, just a
164
- pointer for maintainers who want to opt into the artefact-engagement
165
- telemetry layer. Consumers can ignore it; the feature is **default-off**
166
- and stays off unless explicitly enabled.
236
+ Print one-screen hint after summary — no question, no prompt, just pointer
237
+ for maintainers who want to opt into artefact-engagement telemetry layer.
238
+ Consumers can ignore; feature is **default-off** and stays off unless
239
+ explicitly enabled.
167
240
 
168
241
  ```
169
242
  ℹ️ Maintainer telemetry (opt-in)
@@ -181,20 +254,27 @@ Skip this block in cloud surfaces (no settings file, no log path).
181
254
 
182
255
  ## Gotchas
183
256
 
184
- - `.agent-settings.yml` is git-ignored. This command never commits.
185
- - One question per turn. The iron law from `ask-when-uncertain` applies;
186
- do not stack questions 2–6 into a single prompt.
257
+ - `.agent-settings.yml` is git-ignored. Command never commits.
258
+ - One question per turn. Iron law from `ask-when-uncertain` applies; do
259
+ not stack questions 2–9 into single prompt.
187
260
  - Re-running `/onboard` when `onboarded: true` is allowed — walk through
188
- all steps again and rewrite the values the user confirms.
189
- - Never overwrite a non-empty value without asking (applies to `user_name`
190
- and `ide`).
261
+ all steps again and rewrite values user confirms.
262
+ - Never overwrite non-empty value without asking (applies to `user_name`,
263
+ `ide`).
264
+ - **User-global file is opt-in, one-shot, never silent.** Step 2 captures
265
+ intent, step 9 re-confirms before actual write. If
266
+ `~/.config/agent-config/agent-settings.yml` already exists when
267
+ `/onboard` starts, step 2 is skipped entirely — re-onboarding never
268
+ silently rewrites developer's cross-project defaults. Use
269
+ `/sync-agent-settings` (project-scoped only) or edit file manually for
270
+ mid-life changes.
191
271
 
192
272
  ## Cloud Behavior
193
273
 
194
274
  On cloud surfaces (Claude.ai Web, Skills API) this command is **fully inert** —
195
- there is no `.agent-settings.yml` to write, no `onboarding.onboarded` key to
196
- flip, and no local IDE/rtk environment to capture. First-run setup is a
197
- local-agent concern; the cloud agent should proceed without invoking it.
275
+ no `.agent-settings.yml` to write, no `onboarding.onboarded` key to flip,
276
+ no local IDE/rtk env to capture. First-run setup is local-agent concern;
277
+ cloud agent should proceed without invoking it.
198
278
 
199
279
  ## See also
200
280
 
@@ -202,3 +282,4 @@ local-agent concern; the cloud agent should proceed without invoking it.
202
282
  - [`set-cost-profile`](set-cost-profile.md) — isolated profile change
203
283
  - [`layered-settings`](../docs/guidelines/agent-infra/layered-settings.md) — merge rules for mid-life edits
204
284
  - [`agent-settings` template](../templates/agent-settings.md) — settings reference
285
+ - [`scripts/_lib/agent_settings.py`](../scripts/_lib/agent_settings.py) — centralized loader + whitelist that consumes the user-global file
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: orchestrate
3
+ cluster: orchestrate
4
+ skills: [subagent-orchestration]
5
+ description: Run a YAML pipeline defined under `.agent-config/orchestrations/` — chains personas / skills / commands / sub-agents per the orchestration-dsl-v1 contract
6
+ disable-model-invocation: true
7
+ suggestion:
8
+ eligible: true
9
+ trigger_description: "run a saved orchestration / pipeline / chain"
10
+ trigger_context: "user names a pipeline file or asks to replay a chain"
11
+ ---
12
+
13
+ # orchestrate
14
+
15
+ ## Instructions
16
+
17
+ Execute a YAML pipeline file from `.agent-config/orchestrations/`
18
+ against the current workspace. Pipelines are deterministic chains of
19
+ personas, skills, commands, and sub-agents pinned by the
20
+ [`orchestration-dsl-v1`](../docs/contracts/orchestration-dsl-v1.md)
21
+ contract.
22
+
23
+ This command is the **runtime** side of the contract. The schema and
24
+ the linter (`scripts/lint_orchestration_dsl.py`) live on the authoring
25
+ side; this command reads the same shape and dispatches each step.
26
+
27
+ ### 1. Resolve the pipeline file
28
+
29
+ - The user passes either a pipeline name (`pr-readiness-check`) or a
30
+ path (`.agent-config/orchestrations/pr-readiness-check.yaml`).
31
+ - Resolve to a path under `.agent-config/orchestrations/`. Refuse
32
+ paths outside that directory — pipelines live in one place.
33
+ - If the file does not exist, list the available pipelines and stop.
34
+
35
+ ### 2. Validate before run
36
+
37
+ Run the linter against the resolved file:
38
+
39
+ ```
40
+ python3 scripts/lint_orchestration_dsl.py --file <path>
41
+ ```
42
+
43
+ Exit code ≠ 0 → surface the linter output and stop. **Never** run
44
+ a pipeline that fails its own schema check.
45
+
46
+ ### 3. Collect inputs
47
+
48
+ For each `inputs[]` entry in the pipeline:
49
+
50
+ - If the user supplied a value on invocation (`/orchestrate pr-readiness-check diff_target=feature/x`)
51
+ use it.
52
+ - Else use the `default` field.
53
+ - Else ask **one** question per missing input, in order. Stop after
54
+ the first unanswered required input — pipelines are batch-friendly
55
+ by design, but `ask-when-uncertain` still applies.
56
+
57
+ ### 4. Dispatch the steps
58
+
59
+ Walk `steps[]` in order. For each step:
60
+
61
+ | `kind` | Dispatch path |
62
+ |---|---|
63
+ | `skill` | Invoke the skill identified by `ref` with the resolved `with` block. |
64
+ | `command` | Run the slash-command identified by `ref` as if the user had typed it. |
65
+ | `persona` | Set `roles.active_role` to `ref` for the next dependent step; does not produce its own `output`. |
66
+ | `subagent` | Delegate to [`subagent-orchestration`](../skills/subagent-orchestration/SKILL.md) using `ref` as the mode name. |
67
+
68
+ Capture each step's output in an in-memory `outputs[step.id]` map.
69
+ `${{ inputs.X }}` and `${{ steps.Y.output }}` are substituted via
70
+ string replacement only — no expressions, no shell-out.
71
+
72
+ ### 5. Honour `when`
73
+
74
+ If a step has a `when` field, evaluate it as one of:
75
+
76
+ - `${{ steps.X.output }} == "<literal>"`
77
+ - `steps.X.success` / `steps.X.failure`
78
+
79
+ Anything else → stop the run with a clear error. The DSL is
80
+ deliberately tiny; richer logic belongs in a skill, not in the
81
+ pipeline file.
82
+
83
+ ### 6. Halt on hard failure
84
+
85
+ A step failure ends the pipeline immediately. Surface:
86
+
87
+ - the failing step id and kind/ref
88
+ - the error or non-zero exit
89
+ - the steps that ran cleanly before it
90
+
91
+ Do **not** continue past a failure unless a downstream step has a
92
+ `when: steps.X.failure` guard explicitly authorizing it.
93
+
94
+ ### 7. Produce the delivery report
95
+
96
+ When the pipeline reaches the end of `steps[]`:
97
+
98
+ - Resolve every `outputs[name]` entry by substituting the captured
99
+ step outputs.
100
+ - Print a Markdown delivery report:
101
+ - pipeline name + resolved input values
102
+ - per-step verdict (✅ / ❌, ref, one-line summary)
103
+ - the resolved `outputs:` map at the bottom
104
+
105
+ ### 8. Audit trail
106
+
107
+ Per [`audit-log-v1`](../docs/contracts/audit-log-v1.md), append
108
+ one JSONL entry per step boundary to the current month's audit file
109
+ under `agents/state/audit/`. Counts + ids only — never the step's
110
+ output body.
111
+
112
+ ### 9. What this command does NOT do
113
+
114
+ - Edit the pipeline file. Authoring is human or skill-driven.
115
+ - Commit, push, or open PRs. Those gates live elsewhere.
116
+ - Branch or invent steps. The pipeline file is the source of truth.
117
+
118
+ ## See also
119
+
120
+ - Contract: [`orchestration-dsl-v1.md`](../docs/contracts/orchestration-dsl-v1.md)
121
+ - Linter: `scripts/lint_orchestration_dsl.py`
122
+ - Subagent runtime: [`subagent-orchestration`](../skills/subagent-orchestration/SKILL.md)
123
+ - Audit emission: [`audit-log-v1.md`](../docs/contracts/audit-log-v1.md)
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: sync-gitignore:fix
3
+ cluster: sync-gitignore
4
+ sub: fix
5
+ description: Scrub legacy pre-`/agents/` patterns from the consumer's .gitignore (inside or outside the managed block) and re-sync the canonical entries
6
+ disable-model-invocation: true
7
+ suggestion:
8
+ eligible: true
9
+ trigger_description: "fix .gitignore garbage, clean up legacy agent-config entries, my .gitignore has stale agent entries, /sync-gitignore is not picking up the right paths"
10
+ trigger_context: "consumer project carries pre-/agents/ runtime patterns (.agent-chat-history, .agent-prices.md) at the root from an older install"
11
+ ---
12
+
13
+ # /sync-gitignore:fix
14
+
15
+ Cleanup sibling of [`/sync-gitignore`](../sync-gitignore.md). Strips
16
+ legacy root-level patterns (pre-`/agents/` runtime artefacts —
17
+ `.agent-chat-history`, `.agent-chat-history.bak`,
18
+ `.agent-chat-history.*.bak`, `.agent-prices.md`, `.council-tmp/`) from
19
+ **anywhere** in the consumer's `.gitignore` — inside or outside the
20
+ managed block — then re-runs the regular sync so the current canonical
21
+ `/agents/`-prefixed entries land in the block.
22
+
23
+ Use when:
24
+
25
+ - An older installer (pre-May 2026) dropped root-level `.agent-chat-history`
26
+ / `.agent-prices.md` lines that the current scripts no longer recognise.
27
+ - A hand-edit added one of those legacy paths and it now conflicts with
28
+ the managed `/agents/...` entry.
29
+ - `/sync-gitignore` reports "already in sync" but git is still ignoring
30
+ files at the wrong paths.
31
+
32
+ ## When NOT to use
33
+
34
+ - To remove **user-added** lines from inside the block → that is
35
+ `--replace` on the base command, and it is destructive. This
36
+ sub-command only touches the legacy pattern list — nothing else.
37
+ - To delete the entire managed block → do it by hand.
38
+ - To migrate runtime files themselves (move `.agent-chat-history` →
39
+ `agents/.agent-chat-history`) → the installer's
40
+ `migrate_legacy_root_infra` step handles that. This sub-command only
41
+ fixes `.gitignore`.
42
+
43
+ ## Steps
44
+
45
+ ### 1. Locate script and target
46
+
47
+ Same resolution order as [`/sync-gitignore`](../sync-gitignore.md):
48
+
49
+ 1. `./agent-config/scripts/sync_gitignore.py`
50
+ 2. `vendor/event4u/agent-config/scripts/sync_gitignore.py`
51
+ 3. `node_modules/@event4u/agent-config/scripts/sync_gitignore.py`
52
+
53
+ Target is `<project_root>/.gitignore`. If no `.gitignore` exists,
54
+ stop — there is nothing to fix:
55
+
56
+ ```
57
+ > 📝 No .gitignore found at <project_root>. Nothing to clean up.
58
+ ```
59
+
60
+ ### 2. Dry-run with cleanup
61
+
62
+ Run:
63
+
64
+ ```bash
65
+ python3 <script> --cleanup-legacy --dry-run
66
+ ```
67
+
68
+ Capture stdout (unified diff) and stderr (summary line listing the
69
+ legacy entries that would be removed). Three outcomes:
70
+
71
+ - **Nothing legacy + block in sync** → tell the user and stop:
72
+ ```
73
+ > ✅ .gitignore already clean — no legacy patterns, block in sync.
74
+ ```
75
+ - **Diff produced** → show it and ask:
76
+ ```
77
+ > 🧹 /sync-gitignore:fix would clean up .gitignore:
78
+ >
79
+ > {diff}
80
+ >
81
+ > Summary: would remove {N} legacy entr{y|ies}: {names}
82
+ > would add {M} entr{y|ies} to the managed block
83
+ >
84
+ > 1. Apply — write the changes
85
+ > 2. Skip — leave .gitignore untouched
86
+ ```
87
+ - **Script error** (exit 2) → print the error and stop; do not prompt.
88
+
89
+ ### 3. Act on the choice
90
+
91
+ - `1` (Apply) → re-run **without** `--dry-run`:
92
+ ```bash
93
+ python3 <script> --cleanup-legacy
94
+ ```
95
+ Confirm with the script's own summary lines (removed-legacy count and
96
+ added-entries count both surface there).
97
+ - `2` (Skip) → stop. No changes made.
98
+
99
+ Free-text replies (`"nö"`, `"leave it"`, unrecognized input) count as
100
+ `2`. Never write on ambiguous input.
101
+
102
+ ### 4. Suggest the migration check (informational, do NOT auto-run)
103
+
104
+ If the cleanup removed `.agent-chat-history` or `.agent-prices.md`,
105
+ mention that the **file** at the root (if still present) may need to
106
+ move to `agents/`. The installer does this automatically via
107
+ [`migrate_legacy_root_infra`](../../../scripts/install.sh); the
108
+ agent does not run it from this command. One line of guidance is
109
+ enough:
110
+
111
+ ```
112
+ > ℹ️ If `.agent-chat-history` still sits at the project root, re-run the installer (or move it to `agents/.agent-chat-history` by hand) so the runtime can find it again.
113
+ ```
114
+
115
+ ## Rules
116
+
117
+ - **Append-only by default** — `--cleanup-legacy` removes legacy
118
+ patterns only. User-added non-legacy lines (inside or outside the
119
+ block) survive untouched.
120
+ - **Never combine with `--replace`** — the destructive full-block
121
+ rewrite is a separate concern; mixing the two surprises users.
122
+ - **Dry-run first, always** — the user must see the diff before any
123
+ write.
124
+ - **Do NOT push, commit, or modify other files** — this command writes
125
+ to `.gitignore` only.
126
+
127
+ ## See also
128
+
129
+ - [`/sync-gitignore`](../sync-gitignore.md) — append-only sync of the
130
+ managed block (no legacy cleanup)
131
+ - [`scripts/sync_gitignore.py`](../../../scripts/sync_gitignore.py) —
132
+ the helper (`--cleanup-legacy` flag)
133
+ - [`scripts/install.sh`](../../../scripts/install.sh) —
134
+ `migrate_legacy_root_infra` (moves the **files**, complement to this
135
+ command which fixes the **ignore rules**)
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  name: sync-gitignore
3
+ cluster: sync-gitignore
3
4
  description: Sync the `event4u/agent-config` block in the consumer project's .gitignore — adds missing entries, preserves user-added lines, shows a diff before writing
4
5
  disable-model-invocation: true
5
6
  suggestion:
@@ -9,6 +10,28 @@ suggestion:
9
10
 
10
11
  # /sync-gitignore
11
12
 
13
+ Top-level entry point for the `/sync-gitignore` family. Bare `/sync-gitignore`
14
+ runs the interactive append-only sync described below. The `:fix`
15
+ sub-command additionally scrubs legacy patterns (pre-`/agents/` layout)
16
+ from anywhere in the consumer's `.gitignore` before re-syncing.
17
+
18
+ ## Sub-commands
19
+
20
+ | Sub-command | Routes to | Purpose |
21
+ |---|---|---|
22
+ | `/sync-gitignore` (bare) | this file (`## Default flow`) | Interactive — append-only sync of the managed block, dry-run preview, confirm before write |
23
+ | `/sync-gitignore:fix` | `commands/sync-gitignore/fix.md` | Cleanup — strip legacy root-level patterns (pre-`/agents/` layout) wherever they appear, then sync |
24
+
25
+ ## Dispatch
26
+
27
+ 1. Parse the user's argument: `/sync-gitignore[:<sub>] [args]`.
28
+ 2. Bare `/sync-gitignore` → run the `## Default flow` below verbatim.
29
+ 3. `/sync-gitignore:fix` → load `commands/sync-gitignore/fix.md` and follow
30
+ its `## Steps` section verbatim.
31
+ 4. Unknown sub-command → print the table above and ask which one.
32
+
33
+ ## Default flow
34
+
12
35
  Ensures the consumer project's `.gitignore` contains every entry the
13
36
  package expects to be ignored (symlinked `.augment/` subdirectories,
14
37
  `/agent-config` CLI wrapper, `.agent-settings*`, `agents/.agent-chat-history*`).
@@ -23,7 +46,7 @@ Use when:
23
46
  setup, or installer ran with `--skip-gitignore`).
24
47
  - You want to audit what the block **should** look like without writing.
25
48
 
26
- ## When NOT to use
49
+ ### When NOT to use
27
50
 
28
51
  - To disable logging or change what is logged → that is
29
52
  `chat_history.enabled` in `.agent-settings.yml`, not `.gitignore`.
@@ -31,8 +54,8 @@ Use when:
31
54
  re-remove its own entries.
32
55
  - To change what the block contains → edit
33
56
  `config/gitignore-block.txt` in the package repo and re-release.
34
-
35
- ## Steps
57
+ - To clean up legacy garbage from older installs → use
58
+ [`/sync-gitignore:fix`](sync-gitignore/fix.md) instead.
36
59
 
37
60
  ### 1. Locate script and target
38
61
 
@@ -88,9 +111,11 @@ Free-text replies (`"nö"`, `"leave it"`, unrecognized input) count as
88
111
  Do **not** suggest `--replace` by default. It rewrites the block in
89
112
  full and drops user-added lines inside the block — destructive.
90
113
  Mention it only if the user explicitly asks to clean up or reset the
91
- block, and confirm once more before running it.
114
+ block, and confirm once more before running it. For removing legacy
115
+ root-level patterns (not user-added lines), prefer
116
+ [`/sync-gitignore:fix`](sync-gitignore/fix.md).
92
117
 
93
- ## Gotchas
118
+ ## Rules
94
119
 
95
120
  - The script honors the explicit `# event4u/agent-config — END` marker.
96
121
  Legacy blocks without it get the marker added automatically on the
@@ -99,6 +124,7 @@ block, and confirm once more before running it.
99
124
  They do not survive `--replace`.
100
125
  - Changes to `config/gitignore-block.txt` require a package update in
101
126
  the consumer project before this command can apply them.
127
+ - **Do NOT chain sub-commands.** One `/sync-gitignore <sub>` per turn.
102
128
 
103
129
  ## See also
104
130
 
@@ -21,6 +21,11 @@ Use this skill when:
21
21
  * Reviewing post-task learnings or retrospectives
22
22
  * Deciding whether a learning belongs in a rule or a skill
23
23
  * After completing a task — reflecting on what worked or caused friction
24
+ * Mining the audit log (`agents/state/audit/<YYYY-MM>.jsonl`,
25
+ [`audit-log-v1`](../../../docs/contracts/audit-log-v1.md)) surfaced
26
+ a repeated phase pattern via
27
+ [`extract_audit_patterns.py`](../../../scripts/extract_audit_patterns.py)
28
+ — the pattern's `count` ≥ 2 already satisfies the repetition gate
24
29
 
25
30
  Do not use this skill when:
26
31
 
@@ -206,8 +211,10 @@ Mandatory fields the draft MUST fill:
206
211
  * `source_learning` — path to the `agents/learnings/<date>-<slug>.md`
207
212
  file this proposal was captured from
208
213
  * `evidence` — **at least two independent** references (PR, issue,
209
- incident, review-comment, test-failure); entries that all resolve
210
- to the same PR are rejected by the gate
214
+ incident, review-comment, test-failure, **or audit-log line ids**
215
+ per [`audit-log-v1`](../../../docs/contracts/audit-log-v1.md));
216
+ entries that all resolve to the same PR or the same audit-log
217
+ `run_id` are rejected by the gate (independence floor)
211
218
  * `Proposed artefact` (§4) — the full draft body, no `TODO` / `TBD`
212
219
  * `Success signal` (§7) — one metric, one baseline, one target, one
213
220
  evaluation date
@@ -295,6 +302,27 @@ audio) goes through the upstream `markitdown-mcp` server first; only
295
302
  write a custom extractor if `markitdown` cannot handle the format and
296
303
  the gap is documented in its skill body.
297
304
 
305
+ ## Audit-derived learnings (optional source)
306
+
307
+ When the input is a pattern surfaced by
308
+ [`extract_audit_patterns.py`](../../../scripts/extract_audit_patterns.py)
309
+ mining `agents/state/audit/<YYYY-MM>.jsonl`
310
+ ([`audit-log-v1`](../../../docs/contracts/audit-log-v1.md)):
311
+
312
+ 1. Treat the script's pattern record as the **State the learning**
313
+ step input (§1) — `pattern.summary` is the one-sentence
314
+ statement, `pattern.line_ids` is the evidence.
315
+ 2. The repetition gate is already satisfied for `count ≥ 2`. Skip
316
+ to §3 (decide the target) — overlap check (§4) and proposal
317
+ draft (§8) remain mandatory.
318
+ 3. Independence floor still applies: two line ids from the same
319
+ `run_id` count as **one** piece of evidence. The mining script
320
+ already de-duplicates by `run_id`; the gate trusts that output.
321
+ 4. Audit-derived proposals MUST set
322
+ `source_learning: agents/state/audit/<YYYY-MM>.jsonl#<line_ids>`
323
+ and link the mining-script run id, so the human reviewer can
324
+ reproduce the pattern from the raw audit log.
325
+
298
326
  ## Environment notes
299
327
 
300
328
  Prefer updating existing rule/skill when possible.