@event4u/agent-config 2.1.0 → 2.2.1

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 (38) hide show
  1. package/.agent-src/rules/no-cheap-questions.md +11 -2
  2. package/.agent-src/skills/readme-writing-package/SKILL.md +24 -0
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +69 -0
  5. package/README.md +71 -6
  6. package/docs/DISTRIBUTION_CHECKLIST.md +7 -6
  7. package/docs/architecture.md +1 -1
  8. package/docs/contracts/tier-3-contrib-plugin.md +129 -0
  9. package/docs/decisions/ADR-007-agent-discovery-scopes.md +286 -0
  10. package/docs/decisions/ADR-008-installed-tools-manifest.md +160 -0
  11. package/docs/decisions/INDEX.md +2 -0
  12. package/docs/getting-started.md +1 -1
  13. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +32 -0
  14. package/docs/guidelines/agent-infra/installed-tools-manifest.md +135 -0
  15. package/docs/installation.md +83 -27
  16. package/docs/setup/per-ide/aider.md +1 -1
  17. package/docs/setup/per-ide/claude-code.md +1 -1
  18. package/docs/setup/per-ide/claude-desktop.md +8 -4
  19. package/docs/setup/per-ide/cline.md +2 -2
  20. package/docs/setup/per-ide/codex.md +1 -1
  21. package/docs/setup/per-ide/copilot.md +2 -2
  22. package/docs/setup/per-ide/cursor.md +2 -2
  23. package/docs/setup/per-ide/gemini-cli.md +1 -1
  24. package/docs/setup/per-ide/windsurf.md +2 -2
  25. package/docs/troubleshooting.md +4 -4
  26. package/package.json +1 -1
  27. package/scripts/_cli/cmd_export.py +157 -0
  28. package/scripts/_cli/cmd_sync.py +162 -0
  29. package/scripts/_cli/cmd_update.py +23 -1
  30. package/scripts/_cli/cmd_validate.py +164 -0
  31. package/scripts/_lib/installed_lock.py +160 -0
  32. package/scripts/_lib/installed_tools.py +237 -0
  33. package/scripts/agent-config +78 -1
  34. package/scripts/install +43 -10
  35. package/scripts/install.py +975 -14
  36. package/templates/agent-config-wrapper.sh +1 -1
  37. package/templates/consumer-settings/README.md +1 -1
  38. package/templates/marketing-copy.yml +6 -5
@@ -0,0 +1,286 @@
1
+ ---
2
+ adr: 007
3
+ status: accepted
4
+ date: 2026-05-12
5
+ decision: global-default-install-with-export-subcommand
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: post-v2.1.0 · simplicity-and-everywhere
9
+ ---
10
+
11
+ # ADR-007 — Agent Discovery Scopes: Global-Default Install Model
12
+
13
+ > **Note (post-acceptance):** the one-shot installer command was later
14
+ > renamed from `npx @event4u/create-agent-config init` to
15
+ > `npx @event4u/agent-config init` when the standalone wrapper package
16
+ > was retired. References to the old command name below are preserved
17
+ > for historical accuracy; the discovery-scope decision itself is
18
+ > unchanged. See `CHANGELOG.md` → `[Unreleased]` → "Package
19
+ > consolidation".
20
+
21
+ ## Status
22
+
23
+ **Accepted** · 2026-05-12 · signed off by Matze after Council Round 3 convergence. Implementation tracked in `agents/roadmaps/road-to-global-first-install.md`.
24
+
25
+ Originates from user ask: "Es macht keinen Sinn, das paket nicht
26
+ global zu installieren." Validated through AI Council (2 + 1 rounds,
27
+ 2026-05-12 · members claude-sonnet-4-5 + gpt-4o). Council session:
28
+ [`agents/council-sessions/2026-05-12-global-first-strategy/`](../../agents/council-sessions/2026-05-12-global-first-strategy/). <!-- council-ref-allowed: ADR decision trace -->
29
+
30
+ ## Context
31
+
32
+ `event4u/agent-config` v2.1.0 ships strictly via
33
+ `npx @event4u/create-agent-config init`, project-scoped. The package
34
+ must serve **10 distinct AI agents**, each with its own discovery
35
+ rules — both user-scope (global) and project-scope (workspace) paths.
36
+ Today the CLI only installs project-locally; a `global` subcommand
37
+ in `scripts/agent-config` returns "reserved for Phase 3 of
38
+ road-to-simplicity-and-everywhere".
39
+
40
+ The user wants global to be the **default** path, not a special case.
41
+ Before flipping the default, we needed to answer four blocking
42
+ questions: (1) is global-default sound across all 10 agents? (2) how
43
+ do we detect user intent? (3) how do we handle tools that
44
+ project-scope wins? (4) how do we preserve version reproducibility
45
+ once `npx` resolves global state?
46
+
47
+ ### Relationship to the retired `--global` (commit `5388de25`)
48
+
49
+ A previous `--global` flag existed in `scripts/install.py` and was
50
+ **retired** on 2026-05-12 alongside the composer/npm drop
51
+ (`road-to-portable-runtime-and-update-check` step P0.5,
52
+ [archived roadmap](../../agents/roadmaps/archive/road-to-portable-runtime-and-update-check.md)).
53
+ The retired design was an **in-project symlink scheme** driven by
54
+ `templates/global-install-manifest.yml` — it wrote symlinks *into the
55
+ project* pointing back at a curated set in the user's home. Pain that
56
+ killed it: gitignore drift, link breakage on rebase / worktree, and a
57
+ manifest separate from the main install set that drifted out of sync.
58
+
59
+ ADR-007's `--global` is a **different mechanism with the same flag
60
+ name**:
61
+
62
+ | Dimension | Retired `--global` (pre `5388de25`) | ADR-007 `--global` (this decision) |
63
+ |---|---|---|
64
+ | Files live in | Project repo (`.claude/`, …) as symlinks | User home (`~/.claude/`, …) as **real files** |
65
+ | Manifest | Separate curated `global-install-manifest.yml` | Same full set as project install (D4) |
66
+ | Project-side artefacts | Symlinks, gitignored | None by default; opt-in via `export` (D3) |
67
+ | Version-pin governance | None — drift via symlink target swap | `~/.config/agent-config/installed.lock` (D5) |
68
+ | In-project gitignore footprint | Required and brittle | Zero |
69
+
70
+ The retired pain is structurally absent from the new design: no
71
+ in-project symlinks, no manifest split, an explicit version lockfile.
72
+ The flag name is reused; the implementation is rebuilt.
73
+
74
+ ### Verified per-agent discovery matrix (May 2026)
75
+
76
+ | Agent | User-scope (global) | Project-scope | Precedence |
77
+ |---|---|---|---|
78
+ | Claude Code | `~/.claude/{skills,commands,rules,settings.json}` + `~/.claude/CLAUDE.md` | `.claude/…` + `CLAUDE.md` | managed > user > project (skills) |
79
+ | Claude Desktop | `~/.claude/` (shared) | — | user only |
80
+ | Cursor | User Rules (app settings) + `~/.cursor/` (MCP) | `.cursor/rules/*.mdc` | team > user > project |
81
+ | Windsurf | `~/.codeium/windsurf/global_rules.md` + `…/global_workflows/` | `.windsurfrules` + `.windsurf/{rules,workflows}/` | **workspace > global** |
82
+ | Cline | `~/Documents/Cline/Rules/` | `.clinerules` (file or dir) | **workspace > global** |
83
+ | Augment Code | `~/.augment/{rules,commands}/` | `.augment/{rules,commands}` + `.augment-guidelines` + `AGENTS.md` | workspace > user (cmds); user always-on (rules) |
84
+ | GitHub Copilot | `~/.copilot/copilot-instructions.md` (CLI) + Personal Instructions (settings) | `.github/copilot-instructions.md` + `.github/instructions/*` | personal > repo > org |
85
+ | Gemini CLI | `~/.gemini/GEMINI.md` + `~/.gemini/settings.json` | `GEMINI.md` (hierarchical) + `.gemini/settings.json` | **project > user > system** |
86
+ | Aider | `~/.aider.conf.yml` + `~/.aider.conventions.md` | `.aider.conf.yml` (git root) + `CONVENTIONS.md` | last loaded wins |
87
+ | OpenAI Codex | `~/.codex/AGENTS.md` (+ override) + `$HOME/.agents/skills` | `AGENTS.md` (repo + nested) + `.agents/skills` + `.codex/config.toml` | closer-to-cwd wins |
88
+
89
+ **Finding:** every supported agent has a user-scope path. Global
90
+ install is technically viable across the entire matrix.
91
+
92
+ **Asymmetry that bit the original strategy:** Windsurf and Cline are
93
+ `workspace > global` — a project-local override silently wins. Gemini
94
+ is `project > user > system`. Claude Code is `user > project` for
95
+ skills. A symlink-bridge approach (originally proposed) cannot give a
96
+ consistent cross-tool experience because per-tool precedence rules
97
+ differ.
98
+
99
+ ## Council Process
100
+
101
+ | Round | Members | Cost (actual) | Verdict |
102
+ |---|---|---|---|
103
+ | 1 + 2 (interleaved) | claude-sonnet-4-5 + gpt-4o | $0.0443 | claude: **REJECT** · gpt-4o: **MODIFY** |
104
+ | 3 (targeted resolution) | same | $0.0252 | **3/4 convergence** |
105
+
106
+ Full responses:
107
+ [`responses.json`](../../agents/council-sessions/2026-05-12-global-first-strategy/responses.json), <!-- council-ref-allowed: ADR decision trace -->
108
+ [`responses-round3.json`](../../agents/council-sessions/2026-05-12-global-first-strategy/responses-round3.json). <!-- council-ref-allowed: ADR decision trace -->
109
+
110
+ ## Decision
111
+
112
+ Adopt **Global-Default Install with Export-Subcommand** in five parts.
113
+
114
+ ### D1 — Install scope: global is the default
115
+
116
+ `npx @event4u/create-agent-config init` defaults to **user-scope
117
+ install** (`~/.claude/`, `~/.cursor/`, `~/.codeium/windsurf/`,
118
+ `~/.augment/`, `~/Documents/Cline/Rules/`, `~/.copilot/`, `~/.gemini/`,
119
+ `~/.aider.conventions.md`, `~/.codex/`). Project-scope install is
120
+ **opt-in** via `--project[=<dir>]`. Global is no longer a flag — it
121
+ is the brand promise.
122
+
123
+ Rationale: one npx invocation = configured everywhere. Per-project
124
+ overrides remain available via existing `.agent-settings.yml` merge
125
+ chain (`~/.config/agent-config/agent-settings.yml` → project
126
+ `.agent-settings.yml` → CLI flags).
127
+
128
+ ### D2 — Init UX: prompt only on ambiguity
129
+
130
+ | Signal | Behaviour |
131
+ |---|---|
132
+ | CWD has existing `.agent-settings.yml` | Install **project** (current behaviour preserved) |
133
+ | CWD has `package.json` / `composer.json` / `pyproject.toml` AND existing AI-tool config (`.claude/`, `.cursor/`, etc.) | Prompt: `Project (current dir) / User (~/) / Custom path` |
134
+ | CWD has existing `~/.claude/CLAUDE.md` and command would overwrite | Prompt: `Merge / Backup-and-replace / Abort` — **Hard Floor** |
135
+ | Anything else (incl. CWD = `~/`, empty dir, dotfile-git repos) | Install **global**, no prompt |
136
+
137
+ `.git/` presence is **explicitly not a signal** (monorepos, dotfile
138
+ managers, Hg/SVN workspaces all break it). Replaced by multi-signal
139
+ detection + collision-triggered prompt.
140
+
141
+ ### D3 — Bridge → Export
142
+
143
+ The originally proposed symlink-bridge subcommand is **rejected**.
144
+ Replaced by:
145
+
146
+ ```
147
+ agent-config export --tool=<x> --output=<path> [--force]
148
+ ```
149
+
150
+ Behaviour:
151
+ - Writes a **real file** (no symlink) with the resolved content for
152
+ the named tool, into the user-specified path.
153
+ - Idempotent. `--force` overwrites; default refuses on existing file
154
+ with non-matching content (Hard Floor).
155
+ - User decides path — no canonical defaults baked in (tool-specific
156
+ paths drift upstream).
157
+ - Use cases: committing `.github/copilot-instructions.md` for team
158
+ sharing, versioning `AGENTS.md` or `CLAUDE.md` in repo, exporting
159
+ curated subsets to `docs/ai-context.md`.
160
+
161
+ Rejected: symlink-bridge. Reasons (council-converged):
162
+ - Tool-precedence asymmetry makes symlinks behave differently per
163
+ tool (Windsurf ignores global-bridged file; Claude Code honors it).
164
+ - Symlinks under Git track the pointer path, not content — useless
165
+ on team-mate machines where `~/` differs.
166
+ - Windows symlink privilege (`SeCreateSymbolicLinkPrivilege`) is
167
+ developer-mode / admin-only; corporate Group Policy frequently
168
+ blocks it.
169
+ - EDR tools quarantine symlinks in user-profile config directories
170
+ as "unusual script activity".
171
+
172
+ ### D4 — Manifest: single full set, no curation split
173
+
174
+ Global install ships **all** kernel + tier-1 + tier-2 + skills (same
175
+ manifest as project install). No `templates/global-install-manifest.yml`.
176
+
177
+ Council convergence is **3/4** here — anthropic strongly recommends
178
+ **(a) full** with the argument "10 MB is negligible on any dev
179
+ machine; curated subset creates drift + discovery problems + a second
180
+ command to unblock the rest". OpenAI prefers **(b) curated** but with
181
+ generic rationale.
182
+
183
+ **Residual debate:** the (b) curated camp can still be honored
184
+ post-implementation by adding an `agent-config install --minimal`
185
+ flag without changing the default, if real-world feedback shows the
186
+ full footprint hurts. The decision here is "ship full, narrow later
187
+ if needed" rather than "ship curated, broaden later".
188
+
189
+ ### D5 — Version reproducibility: lockfile
190
+
191
+ ```
192
+ ~/.config/agent-config/installed.lock
193
+ ```
194
+
195
+ Schema:
196
+ ```json
197
+ {
198
+ "version": "2.2.0",
199
+ "installed_at": "2026-05-12T10:30:00Z",
200
+ "tools": ["claude-code", "cursor", "windsurf"]
201
+ }
202
+ ```
203
+
204
+ `init` on existing lock with matching version: **skip**.
205
+ `init` on existing lock with differing version: **fail loud** with
206
+ "Installed: v2.1.0. Current: v2.2.0. Run `agent-config update` or
207
+ `init --force`."
208
+
209
+ `update` is an explicit subcommand. Writes new lock atomically. No
210
+ silent updates ever.
211
+
212
+ ### D6 — Source-repo guard stays
213
+
214
+ `AGENT_CONFIG_ALLOW_SELF_INSTALL=1` requirement when run from inside
215
+ the `agent-config` source repo applies to **both** global and
216
+ project modes (a stray `npx … init` from inside the source tree
217
+ would overwrite the maintainer's `~/.claude/` with package's own
218
+ maintainer manifest).
219
+
220
+ ## Consequences
221
+
222
+ ### Positive
223
+
224
+ - One command, every project: `npx @event4u/create-agent-config init` works
225
+ in `~/`, in a fresh project, in an existing project with no config.
226
+ - Cross-tool consistency: every supported agent gets the same skill /
227
+ rule set from one source of truth in `~/`.
228
+ - No symlink-related fragility (Windows, EDR, Git semantics).
229
+ - Version reproducibility via lockfile is auditable, inspectable, and
230
+ explicit.
231
+
232
+ ### Negative
233
+
234
+ - Behavioural change vs v2.1.0: existing project-installs continue to
235
+ work, but new installs default to a different location. Ships as a
236
+ v2.x release (v2.0.0 was the breaking npx-only cut; subsequent v2.x
237
+ work refines that line — no v3.0.0 planned). Documented migration
238
+ in the release notes is required.
239
+ - Tools with `workspace > global` precedence (Windsurf, Cline,
240
+ Gemini) require user action to bridge: either `agent-config export`
241
+ into the project or `--project` flag at install. Pure global-only
242
+ users on those tools may not see the rules apply inside specific
243
+ repos.
244
+ - A `~/.config/agent-config/installed.lock` introduces a new state
245
+ surface. Uninstall must remove it cleanly; corrupted-lock recovery
246
+ needs documenting.
247
+ - Curation decision is provisional. If `~/.claude/skills/` footprint
248
+ causes complaints, post-launch we may need to add a `--minimal`
249
+ install profile (revisits D4).
250
+
251
+ ### Neutral
252
+
253
+ - The latent `--global` flag in `scripts/install.py` becomes the new
254
+ default codepath — no longer hidden, fully exercised in CI.
255
+ - The `bridge` subcommand reserved for "Phase 3 of
256
+ road-to-simplicity-and-everywhere" is **never built**. Roadmap
257
+ entry should be updated to point at `export` instead.
258
+
259
+ ## Implementation Plan (deferred to roadmap)
260
+
261
+ Out of scope for this ADR. Sequencing target for a separate roadmap:
262
+
263
+ 1. Branch `feat/global-first-install` (requires user permission to
264
+ create — not auto-spawned by this ADR).
265
+ 2. Wire `scripts/install.py --global` through `create-agent-config`
266
+ npx entry + `scripts/agent-config global` subcommand.
267
+ 3. Implement multi-signal detection + collision prompt.
268
+ 4. Implement `agent-config export --tool=<x> --output=<path>`.
269
+ 5. Implement `~/.config/agent-config/installed.lock` + `update`
270
+ subcommand.
271
+ 6. Update `docs/installation.md`, per-IDE setup pages, `README.md`
272
+ tagline.
273
+ 7. Add CI matrix: global-install path on macOS, Linux, Windows
274
+ (lockfile, prompt suppression, Hard Floor enforcement).
275
+ 8. CHANGELOG entry + v2.x migration guide.
276
+
277
+ ## References
278
+
279
+ - Council session:
280
+ [`agents/council-sessions/2026-05-12-global-first-strategy/`](../../agents/council-sessions/2026-05-12-global-first-strategy/) <!-- council-ref-allowed: ADR decision trace -->
281
+ - User-scope discovery matrix sources: agent vendor official docs
282
+ (Claude, Cursor, Windsurf, Cline, Augment, Copilot, Gemini, Aider,
283
+ Codex) accessed 2026-05-12.
284
+ - Prior latent global code: `scripts/install.py` (~280 LOC, never
285
+ reachable from npx entry).
286
+ - Related rule: [`non-destructive-by-default`](../../.augment/rules/non-destructive-by-default.md) — Hard Floor on overwrite of user's existing `~/.claude/CLAUDE.md`.
@@ -0,0 +1,160 @@
1
+ ---
2
+ adr: 008
3
+ status: proposed
4
+ date: 2026-05-12
5
+ decision: committed-installed-tools-manifest-separate-from-settings
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: v2.x · post-global-first-install
9
+ ---
10
+
11
+ # ADR-008 — Installed-Tools Manifest
12
+
13
+ ## Status
14
+
15
+ **Proposed** · 2026-05-12 · pending implementation in Phase 3 of
16
+ [`road-to-global-first-install`](../../agents/roadmaps/road-to-global-first-install.md).
17
+
18
+ Originates from user ask (Matze, 2026-05-12): "Sollten wir auf
19
+ Projektebene festhalten, welche Agents wir initialisiert haben, damit
20
+ bei jedem Sync das Verzeichnis aktualisiert werden kann?" Validated
21
+ through AI Council Round 1 (claude-sonnet-4-5 + gpt-4o, $0.0298 actual,
22
+ both converged on "yes, separate file"). Council session:
23
+ [`agents/council-sessions/2026-05-12-project-settings-and-v1-v2/`](../../agents/council-sessions/2026-05-12-project-settings-and-v1-v2/). <!-- council-ref-allowed: ADR decision trace -->
24
+
25
+ ## Context
26
+
27
+ After ADR-007 (global-first install), each developer's AI tooling
28
+ lives in user-scope paths (`~/.claude/`, `~/.augment/`, …). A project
29
+ no longer carries the AI config in its tree — except for tools with
30
+ `workspace > global` precedence (Windsurf, Cline, Gemini-when-project-
31
+ wins) that **must** keep a project-local bridge.
32
+
33
+ **Resulting gap:** a project has no committed record of which AI
34
+ tools it expects. A new team member cloning the repo cannot tell
35
+ whether the codebase was built with Claude Code, Windsurf, both, or
36
+ five others. Onboarding is "ask the team lead, hope they remember".
37
+
38
+ **Two related but orthogonal problems:**
39
+
40
+ 1. **Bill of materials** — "Which AIs does this project use?"
41
+ 2. **Settings hierarchy** — "How do agents behave in this project?"
42
+
43
+ Today, `.agent-project-settings.yml` (committed) answers #2 (personas,
44
+ quality tools, locked keys). #1 is unanswered.
45
+
46
+ ### What we considered
47
+
48
+ | Option | Verdict |
49
+ |---|---|
50
+ | **A.** Add `installed_tools` block to `.agent-project-settings.yml` | **Rejected** — mixes behaviour with bill-of-materials, creates a "god file" that every sync command must parse and partially ignore. Settings ≠ manifest. |
51
+ | **B.** Put manifest at root: `.agent-installed-tools.lock` | Rejected — root is already crowded with 10+ AI dotfiles; adding another worsens it. |
52
+ | **C.** Separate manifest at `agents/installed-tools.lock` | **Accepted** — co-located with project-shared agent docs; clear name; clear job. |
53
+ | **D.** Skip — let team docs / README describe the tool set | Rejected — README drifts, no machine-readable contract, no drift detection. |
54
+
55
+ Council (Sonnet): _"Settings (user prefs, locked keys, override paths)
56
+ ≠ Manifest (which tools exist). Mixing them creates a god file."_ Both
57
+ members converged on a separate file; the location split (Sonnet
58
+ favoured `installed-tools.lock`, GPT-4o favoured
59
+ `.project-settings.yml`) resolved in favour of Sonnet on the
60
+ separation-of-concerns argument.
61
+
62
+ ## Decision
63
+
64
+ **Adopt option C.** Ship `agents/installed-tools.lock` as the
65
+ committed, schema-versioned bill-of-materials for AI tooling.
66
+
67
+ ### Schema (v1)
68
+
69
+ ```yaml
70
+ schema_version: 1
71
+ agent_config_version: "2.x.y" # version that wrote the file last
72
+ tools:
73
+ - name: claude-code # matches scripts/install.py _VALID_TOOLS
74
+ scope: global # one of: global, project
75
+ bridge_marker: ~/.claude/PROJECT_MANAGED_BY_AGENT_CONFIG
76
+ installed_at: "2026-05-12"
77
+ - name: windsurf
78
+ scope: project # workspace > global → must live in repo
79
+ bridge_marker: .windsurf/PROJECT_MANAGED_BY_AGENT_CONFIG
80
+ installed_at: "2026-05-12"
81
+ ```
82
+
83
+ **Fields:**
84
+
85
+ - `schema_version` — integer; bump on breaking schema changes.
86
+ - `agent_config_version` — last package version that wrote the file.
87
+ - `tools[]` — append-on-init order; not alphabetised (preserves
88
+ installation history for forensics).
89
+ - `tools[].name` — must match `_VALID_TOOLS` in `scripts/install.py`.
90
+ - `tools[].scope` — `global` (user-home install) or `project`
91
+ (workspace-wins tools that need a local bridge).
92
+ - `tools[].bridge_marker` — path to the marker file the installer
93
+ drops to claim ownership. `validate` checks this file exists.
94
+ - `tools[].installed_at` — ISO date; informational only.
95
+
96
+ ### Lifecycle
97
+
98
+ 1. `init --ai <name>` — adds an entry (idempotent). Existing entry
99
+ for same tool with **same scope** is a no-op. Existing entry with
100
+ **different scope** refuses without `--force` (loud warning:
101
+ "tool X is committed as scope=global; you are about to change it
102
+ to project").
103
+ 2. `sync` — reads the lock file, replays every listed tool's install
104
+ (skip if marker present, install if missing). Used by new team
105
+ members.
106
+ 3. `validate` — read-only drift check. Exit 1 if any listed marker
107
+ is missing or scope mismatches the file system. **No auto-fix.**
108
+ 4. Manual edit — discouraged. Lock file is machine-managed; humans
109
+ edit via CLI subcommands.
110
+
111
+ ### Relationship to `.agent-project-settings.yml`
112
+
113
+ | File | Owner | Scope | Example keys |
114
+ |---|---|---|---|
115
+ | `agents/installed-tools.lock` | this ADR | bill of materials | `tools[]`, `scope`, `bridge_marker` |
116
+ | `.agent-project-settings.yml` | layered-settings system | behaviour | `personas.default`, `quality.php.tools`, `locked_keys` |
117
+
118
+ Both committed, both have a single job, never overlap.
119
+
120
+ ## Consequences
121
+
122
+ ### Positive
123
+
124
+ - Onboarding: `git clone` + `npx @event4u/agent-config sync` brings
125
+ every team member's AI tooling to parity.
126
+ - Drift detection: `validate` catches "team lead added Windsurf but
127
+ forgot to commit the lock-file update".
128
+ - Forensics: install order preserved in `tools[]` order; `installed_at`
129
+ pins approximate timestamps.
130
+ - Separation of concerns: behaviour settings stay clean; manifest
131
+ stays focused.
132
+
133
+ ### Negative
134
+
135
+ - New committed file = one more thing to keep in sync with reality.
136
+ Mitigated by **machine-written-only** rule and `validate` CI hook.
137
+ - Scope migration (tool moves between `global` and `project`) needs
138
+ documented playbook in `installed-tools-manifest.md` (Phase 3.5).
139
+ - Single-developer projects gain little — the manifest is overhead
140
+ until a second developer joins. Mitigation: file is optional;
141
+ commands work without it (empty manifest = empty install).
142
+
143
+ ### Neutral
144
+
145
+ - File lives under `agents/`, not at repo root — consistent with
146
+ Matze's preference and council Sonnet's argument that root is
147
+ already crowded.
148
+
149
+ ## Implementation Plan
150
+
151
+ Tracked as Phase 3 of `road-to-global-first-install` (steps 3.1–3.5).
152
+ Ships in a v2.x minor release **after** Phase 2 lands. Out of scope
153
+ for this ADR.
154
+
155
+ ## References
156
+
157
+ - [`ADR-007`](ADR-007-agent-discovery-scopes.md) — global-first install (this ADR depends on it).
158
+ - [`agents/roadmaps/road-to-global-first-install.md`](../../agents/roadmaps/road-to-global-first-install.md) Phase 3.
159
+ - [`agents/council-sessions/2026-05-12-project-settings-and-v1-v2/`](../../agents/council-sessions/2026-05-12-project-settings-and-v1-v2/) — full council transcripts. <!-- council-ref-allowed: ADR decision trace -->
160
+ - [`docs/guidelines/agent-infra/layered-settings.md`](../guidelines/agent-infra/layered-settings.md) — the existing 4-layer settings precedence; this ADR adds a parallel file outside that hierarchy.
@@ -10,6 +10,8 @@ _Auto-generated by `scripts/adr/regenerate_index.py`. Do not edit._
10
10
  | [ADR-004](ADR-004-rule-governance-pruning.md) | Rule Governance Pruning | accepted | 2026-05-08 | — |
11
11
  | [ADR-005](ADR-005-subagent-worktrees.md) | Subagent Worktrees No Auto Merge | accepted | 2026-05-09 | — |
12
12
  | [ADR-006](ADR-006-skill-tools-python-pilot.md) | Skill Tools Python Pilot Pass | accepted | 2026-05-09 | — |
13
+ | [ADR-007](ADR-007-agent-discovery-scopes.md) | Global Default Install With Export Subcommand | accepted | 2026-05-12 | — |
14
+ | [ADR-008](ADR-008-installed-tools-manifest.md) | Committed Installed Tools Manifest Separate From Settings | proposed | 2026-05-12 | — |
13
15
 
14
16
  ## Unnumbered (legacy)
15
17
 
@@ -10,7 +10,7 @@ Pick one entrypoint:
10
10
 
11
11
  ```bash
12
12
  # Recommended — one-shot, no local dependency
13
- npx @event4u/create-agent-config init --tools=claude-code,cursor
13
+ npx @event4u/agent-config init --tools=claude-code,cursor
14
14
 
15
15
  # No-Node fallback — curl | bash entrypoint (downloads a tarball)
16
16
  curl -sSL https://raw.githubusercontent.com/event4u-app/agent-config/main/setup.sh | bash
@@ -106,3 +106,35 @@ correction pattern.
106
106
 
107
107
  Acknowledge once, in the user's language, switch behavior, no
108
108
  excuses (mirrors `language-and-tone` § slip handling).
109
+
110
+
111
+ ## No Cheap Questions — Iron Law 3 detail (paternalistic state options)
112
+
113
+ Companion to `no-cheap-questions` § Iron Law 3. The rule states the
114
+ prohibition; this file lists the patterns and the carve-outs.
115
+
116
+ **Forbidden patterns** (non-exhaustive):
117
+
118
+ - "Stop hier — du hast genug für heute"
119
+ - "Take a break and come back fresh"
120
+ - "Weitermachen wenn frisch"
121
+ - "Du wirkst genervt, sollen wir pausieren?"
122
+ - "Sleep on it"
123
+ - "That's a good stopping point" as a numbered option
124
+ - Any option whose recommendation rests on inferred fatigue,
125
+ frustration, or end-of-day mood.
126
+
127
+ **Carve-outs** — allowed because they cite **observable, in-message**
128
+ evidence, not inferred state:
129
+
130
+ - User said "ich bin müde / done for today / let's stop" **this turn**
131
+ → ack and stop (instruction, not option).
132
+ - Hard Floor confirmation per `non-destructive-by-default` → "confirm
133
+ or abort" is the option, not "rest".
134
+ - Context-window / freshness threshold tripped per `context-hygiene` →
135
+ cite the threshold ("fresh chat at 75%"), do not infer mood.
136
+
137
+ **The rule of thumb**: every numbered option must be a technical /
138
+ scope / sequencing choice with a real trade-off, not a mood-management
139
+ nudge. If the only remaining differentiator is "you might be tired" →
140
+ drop the option, recommend a concrete next step instead.
@@ -0,0 +1,135 @@
1
+ # Installed-Tools Manifest
2
+
3
+ Project-committed bill of materials for AI tooling. Answers the
4
+ question "which AIs does this project use, where do their bridges live,
5
+ and is everyone on the team on the same set?". Canonical schema is
6
+ ADR-008 ([`docs/decisions/ADR-008-installed-tools-manifest.md`](../../decisions/ADR-008-installed-tools-manifest.md)).
7
+ Phase 3 of [`road-to-global-first-install`](../../../agents/roadmaps/road-to-global-first-install.md).
8
+
9
+ This file lives at **`agents/installed-tools.lock`** — committed,
10
+ machine-managed, and orthogonal to `.agent-project-settings.yml`
11
+ (which owns *behaviour*, not *bill of materials*).
12
+
13
+ ## Schema (v1)
14
+
15
+ ```yaml
16
+ schema_version: 1
17
+ agent_config_version: "2.x.y" # last package version that wrote the file
18
+ tools:
19
+ - name: claude-code # must match _VALID_TOOLS in scripts/install.py
20
+ scope: global # one of: global, project
21
+ bridge_marker: ~/.claude/ # validate checks this path exists
22
+ installed_at: "2026-05-12"
23
+ - name: roocode
24
+ scope: project # workspace-wins → must live in repo
25
+ bridge_marker: .roo/rules/agent-config.md
26
+ installed_at: "2026-05-12"
27
+ ```
28
+
29
+ | Field | Owner | Notes |
30
+ |---|---|---|
31
+ | `schema_version` | machine | bumps on breaking schema changes |
32
+ | `agent_config_version` | machine | last writer's package version; `validate` flags drift |
33
+ | `tools[]` | machine | append-on-init order preserved (not alphabetised) |
34
+ | `tools[].name` | machine | one of the 17 valid IDs in `scripts/install.py` |
35
+ | `tools[].scope` | machine | `global` (user-home) or `project` (workspace bridge) |
36
+ | `tools[].bridge_marker` | machine | absolute / `~`-prefixed for global, repo-relative for project |
37
+ | `tools[].installed_at` | machine | ISO date; informational only |
38
+
39
+ The file is **machine-managed**. Hand-editing is discouraged — every
40
+ mutation goes through `init`, `sync`, or `init --force`.
41
+
42
+ ## Workflow
43
+
44
+ ### Team onboarding (clone → sync → done)
45
+
46
+ ```bash
47
+ git clone <repo>
48
+ cd <repo>
49
+ npx @event4u/agent-config sync
50
+ ```
51
+
52
+ `sync` reads `agents/installed-tools.lock`, checks every listed tool's
53
+ bridge marker, and replays `install.py --tools=<id>` for each missing
54
+ one. Tools whose marker is already present are skipped — `sync` is
55
+ idempotent and safe to re-run.
56
+
57
+ ### Adding a tool
58
+
59
+ ```bash
60
+ npx @event4u/agent-config init --tools=<id>
61
+ # or --tools=<id1>,<id2>
62
+ ```
63
+
64
+ `init` writes an entry per tool. Existing entry with the same
65
+ `(name, scope)` → no-op. Entry with **different scope** → loud warning
66
+ and refusal until you pass `--force` (see scope migration below).
67
+
68
+ ### Drift detection (CI gate)
69
+
70
+ ```bash
71
+ npx @event4u/agent-config validate
72
+ ```
73
+
74
+ Read-only. Exit code 1 if any drift is found. Surfaces three drift
75
+ kinds; no auto-fix.
76
+
77
+ | Kind | Trigger | Fix |
78
+ |---|---|---|
79
+ | `marker_missing` | recorded `bridge_marker` does not exist | `agent-config sync` |
80
+ | `scope_divergence` | marker only exists at the *other* scope | `agent-config init --tools=<id> --force` |
81
+ | `version_drift` | manifest's `agent_config_version` ≠ installed package | `agent-config update` then `agent-config init --force` |
82
+
83
+ `--skip-version-check` suppresses the third kind for repositories that
84
+ intentionally pin an older version of the manifest.
85
+
86
+ ## Scope migration
87
+
88
+ Moving a tool between `project` and `global` is supported but loud:
89
+
90
+ 1. Run `init --tools=<id> --scope=<new> --force`. The installer detects
91
+ the conflict, warns, and rewrites the entry only when `--force` is
92
+ present.
93
+ 2. The old bridge is **not** removed automatically — clean up the
94
+ leftover marker yourself (`rm .windsurf/agent-config.md` etc.).
95
+ 3. `validate` afterwards confirms the new state.
96
+
97
+ Reasoning: scope is a project-wide decision; flipping it silently
98
+ would surprise other team members who never asked for the change. The
99
+ loud refusal forces an explicit `--force` so the diff is reviewable in
100
+ the next commit.
101
+
102
+ ## Relationship to other files
103
+
104
+ | File | What it answers | Layer |
105
+ |---|---|---|
106
+ | `agents/installed-tools.lock` | **which AIs?** (this guideline) | bill of materials |
107
+ | `.agent-project-settings.yml` | **how do agents behave?** | layered-settings (team file) |
108
+ | `~/.config/agent-config/installed.lock` | **which package version did I install globally?** | per-developer global lockfile (Phase 1) |
109
+ | `.agent-settings.yml` | **what are my personal preferences in this project?** | layered-settings (developer file) |
110
+
111
+ Each file has one job. They never overlap. The two `.lock` files look
112
+ similar by name but answer different questions: `installed.lock` is
113
+ per-developer / cross-project (the package itself), while
114
+ `installed-tools.lock` is per-project / team-shared (which tools are
115
+ expected in *this* repo).
116
+
117
+ ## CI integration
118
+
119
+ Recommended gate (GitHub Actions / GitLab CI):
120
+
121
+ ```yaml
122
+ - name: Validate installed-tools manifest
123
+ run: npx @event4u/agent-config validate
124
+ ```
125
+
126
+ Pair it with `agent-config sync` in your dev-setup script so new
127
+ contributors get a working environment without reading the manifest by
128
+ hand.
129
+
130
+ ## References
131
+
132
+ - [`ADR-008`](../../decisions/ADR-008-installed-tools-manifest.md) — manifest decision and schema.
133
+ - [`ADR-007`](../../decisions/ADR-007-agent-discovery-scopes.md) — global-first install (prerequisite).
134
+ - [`docs/installation.md`](../../installation.md) — team-onboarding flow.
135
+ - [`layered-settings.md`](layered-settings.md) — parallel settings hierarchy (orthogonal to this manifest).