@event4u/agent-config 2.0.0 → 2.2.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 (41) hide show
  1. package/.agent-src/commands/fix/{pr-bots.md → pr-bot-comments.md} +3 -3
  2. package/.agent-src/commands/fix/{pr.md → pr-comments.md} +6 -6
  3. package/.agent-src/commands/fix/{pr-developers.md → pr-developer-comments.md} +3 -3
  4. package/.agent-src/commands/fix.md +6 -6
  5. package/.agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +2 -2
  6. package/.agent-src/rules/no-cheap-questions.md +11 -2
  7. package/.agent-src/skills/readme-writing-package/SKILL.md +24 -0
  8. package/.claude-plugin/marketplace.json +4 -4
  9. package/CHANGELOG.md +79 -0
  10. package/README.md +76 -12
  11. package/docs/architecture.md +2 -2
  12. package/docs/catalog.md +3 -3
  13. package/docs/contracts/command-clusters.md +3 -3
  14. package/docs/contracts/file-ownership-matrix.json +9 -9
  15. package/docs/contracts/tier-3-contrib-plugin.md +129 -0
  16. package/docs/decisions/ADR-007-agent-discovery-scopes.md +278 -0
  17. package/docs/decisions/ADR-008-installed-tools-manifest.md +160 -0
  18. package/docs/decisions/INDEX.md +2 -0
  19. package/docs/getting-started.md +16 -25
  20. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +32 -0
  21. package/docs/guidelines/agent-infra/installed-tools-manifest.md +135 -0
  22. package/docs/installation.md +116 -49
  23. package/docs/migrations/commands-1.15.0.md +3 -3
  24. package/docs/setup/per-ide/claude-desktop.md +8 -4
  25. package/docs/skills-catalog.md +23 -2
  26. package/docs/troubleshooting.md +20 -32
  27. package/llms.txt +22 -1
  28. package/package.json +1 -1
  29. package/scripts/_cli/cmd_export.py +157 -0
  30. package/scripts/_cli/cmd_sync.py +162 -0
  31. package/scripts/_cli/cmd_update.py +23 -1
  32. package/scripts/_cli/cmd_validate.py +164 -0
  33. package/scripts/_lib/installed_lock.py +160 -0
  34. package/scripts/_lib/installed_tools.py +237 -0
  35. package/scripts/agent-config +62 -0
  36. package/scripts/install +68 -13
  37. package/scripts/install.py +984 -33
  38. package/scripts/install.sh +6 -11
  39. package/templates/agent-config-wrapper.sh +40 -25
  40. package/templates/consumer-settings/README.md +2 -2
  41. package/scripts/setup.sh +0 -230
@@ -30,11 +30,11 @@ If any of these are missing or empty, the installer either didn't run or
30
30
  was interrupted. Re-run it:
31
31
 
32
32
  ```bash
33
- php vendor/bin/install.php --verbose
34
- # or
35
33
  bash scripts/install --verbose
36
34
  # or, to regenerate everything (overwrites existing bridge files):
37
35
  bash scripts/install --force
36
+ # or, for one-shot installs without a local node_modules tree:
37
+ npx @event4u/create-agent-config init --tools=claude-code,cursor
38
38
  ```
39
39
 
40
40
  ### Check 2: Does your agent actually read these directories?
@@ -61,44 +61,34 @@ version explicitly and reinstall the plugin.
61
61
 
62
62
  ---
63
63
 
64
- ## `composer require` / `npm install` runs, but no files were created
64
+ ## Installer ran but no files appeared
65
65
 
66
- Several security-conscious setups disable post-install hooks:
66
+ The v2 distribution does **not** ship a `postinstall` hook — installing
67
+ `@event4u/agent-config` via `npm install -g` only puts the `agent-config`
68
+ binary on `$PATH`; it does not seed any project files. Run the
69
+ orchestrator explicitly inside the project root:
67
70
 
68
71
  ```bash
69
- composer config allow-plugins.false
70
- # or in ~/.npmrc:
71
- ignore-scripts=true
72
- ```
73
-
74
- In that case, the post-install hook never runs. Execute the installer
75
- manually:
72
+ # One-shot, no local checkout required (recommended)
73
+ npx @event4u/create-agent-config init --tools=claude-code,cursor
76
74
 
77
- ```bash
78
- php vendor/bin/install.php # for Composer
79
- # or for npm — invoke the orchestrator directly:
80
- bash node_modules/@event4u/agent-config/scripts/install
75
+ # When the global CLI is installed
76
+ agent-config install --tools=claude-code,cursor
81
77
  ```
82
78
 
83
- The [`scripts/postinstall.sh`](../scripts/postinstall.sh) wrapper prints a
84
- loud error block when the underlying installer fails, so if you saw no
85
- output at all, scripts are likely disabled on your side.
86
-
87
79
  ---
88
80
 
89
- ## Broken symlinks after `composer update` / `npm update`
81
+ ## Broken symlinks after upgrading the package
90
82
 
91
83
  When the package version changes, symlinks that pointed to the old
92
- vendor path may break. Re-run the installer — it is idempotent:
84
+ package path may break. Re-run the installer — it is idempotent:
93
85
 
94
86
  ```bash
95
- php vendor/bin/install.php
96
- # or
97
- bash scripts/install
87
+ npx @event4u/create-agent-config init --tools=claude-code,cursor
98
88
  ```
99
89
 
100
90
  The installer replaces stale symlinks with fresh ones pointing at the
101
- current vendor path.
91
+ current package path.
102
92
 
103
93
  ---
104
94
 
@@ -108,8 +98,8 @@ Native Windows is not a first-class target. The installer relies on Bash
108
98
  and Unix-style symlinks. Recommended setup:
109
99
 
110
100
  1. **WSL2** (preferred): install Ubuntu or a distribution of your choice,
111
- clone the project inside the WSL filesystem, and run `composer
112
- install` / `npm install` from WSL.
101
+ clone the project inside the WSL filesystem, and run
102
+ `npx @event4u/create-agent-config init` from WSL.
113
103
  2. **Git Bash**: works for the basic install, but symlinks require
114
104
  Developer Mode (Windows 10 1703+) or admin privileges. Without either,
115
105
  Git Bash falls back to copies, which means updates will not propagate
@@ -142,15 +132,13 @@ There is no dedicated uninstall command yet. Remove the package and
142
132
  clean up manually:
143
133
 
144
134
  ```bash
145
- # 1. Remove the dependency
146
- composer remove event4u/agent-config
147
- # or
135
+ # 1. Remove the dependency (skip when installed via npx / -g)
148
136
  npm uninstall @event4u/agent-config
149
137
 
150
138
  # 2. Remove generated content from the project
151
139
  rm -rf .augment .claude .cursor .clinerules .windsurfrules GEMINI.md
152
140
  rm -f .agent-settings .agent-settings.yml .agent-settings.backup.key-value
153
- rm -f .github/copilot-instructions.md
141
+ rm -f .github/copilot-instructions.md agent-config
154
142
  # Remove the "# event4u/agent-config" block from .gitignore manually
155
143
  ```
156
144
 
@@ -163,5 +151,5 @@ Keep `AGENTS.md` if you customized it — it is yours, not the package's.
163
151
  Open an [issue](https://github.com/event4u-app/agent-config/issues) with:
164
152
 
165
153
  - your OS and shell,
166
- - PHP / Node / Python versions,
154
+ - Node / Python versions,
167
155
  - full output of `bash scripts/install --verbose --dry-run`.
package/llms.txt CHANGED
@@ -6,6 +6,7 @@ Machine-readable index of all skills in this package. Each line:
6
6
  Source: .agent-src/skills/<name>/SKILL.md
7
7
  Catalog: docs/skills-catalog.md
8
8
 
9
+ accessibility-auditor: Use when reviewing UI for accessibility — WCAG 2.2 AA, keyboard nav, focus, ARIA, contrast, screen-reader semantics — even on 'is this a11y-OK?' or 'mach das barrierefrei'.
9
10
  adr-create: Use when capturing an architectural decision — naming the file, picking the next ADR number, filling Status / Context / Decision / Consequences, and regenerating the index — even without saying 'ADR'.
10
11
  adversarial-review: ONLY when user explicitly requests adversarial review, devil's advocate analysis, stress-testing a plan, or 'poke holes in this' — NOT for regular code review or design feedback.
11
12
  agent-docs-writing: Use when reading, creating, or updating agent documentation, module docs, roadmaps, or AGENTS.md. Understands the full .augment/, agents/, and copilot-instructions structure.
@@ -16,6 +17,7 @@ analysis-skill-router: Use when picking which analysis or project-analysis-* ski
16
17
  api-design: Use when designing APIs, planning endpoints, REST conventions, versioning, or deprecation — even when the user just says 'expose this as an endpoint' without naming API design.
17
18
  api-endpoint: Use when the user says "create endpoint", "new API route", or "add controller". Creates a complete endpoint with Controller, FormRequest, Resource, route, and OpenAPI docs.
18
19
  api-testing: Use when writing API endpoint tests — integration tests, contract validation, response assertions, mocked external services — even when the user says 'test this route' without naming API testing.
20
+ architecture-review-lens: Use when a diff may break system boundaries, dependency direction, or cross-service contracts — fifth judge dispatched by /review-changes alongside the four standard judges.
19
21
  artisan-commands: Use when creating or modifying Artisan commands. Covers clear signatures, safe execution flow, helpful output, and project conventions for console tooling.
20
22
  async-python-patterns: Use when writing Python asyncio code — picking between gather / TaskGroup / wait, structured concurrency, timeouts, cancellation, sync-bridging — decision framework only, cookbook externalized.
21
23
  authz-review: Use when reviewing authorization end-to-end — route → gate → policy → query scope → response filter — before changes to permissions, tenants, ownership, or admin flows.
@@ -28,16 +30,19 @@ code-refactoring: Use when the user says "refactor this", "rename class", or "mo
28
30
  code-review: Use when the user says "review this", "check my code", or wants feedback on changes. Reviews for correctness, quality, security, and coding standards.
29
31
  command-routing: Use when the user invokes a slash command like /create-pr, /commit, /fix-ci, or pastes command file content — routes to the right command with context inference and GitHub API patterns.
30
32
  command-writing: Use when creating or editing a slash command in .agent-src.uncompressed/commands/ — frontmatter, numbered steps, safety gates — even when the user just says 'add a /command for X'.
33
+ competitive-positioning: Use when comparing this package to a peer / competitor — ours-vs-theirs verdict table, axis selection, adoption queue. Triggers on 'how do we compare to X', 'should we adopt their pattern'.
31
34
  composer-packages: Use when building or maintaining a Composer library — versioning, Laravel integration, autoloading, publishing to private registries — even when the user says 'release a new version'.
32
35
  context-authoring: Use when filling in knowledge-layer context files — auth-model, tenant-boundaries, data-sensitivity, deployment-order, observability — interactive walkthrough that turns templates into reviewer fuel.
33
36
  context-document: Use when the user says "create context", "document this area", or wants a structured snapshot of a codebase area for agent orientation.
34
37
  conventional-commits-writing: Use when writing commit messages or squash-merge titles — `feat:`, `fix:`, `chore:`, scopes, breaking changes — even when the user just says 'commit this' without naming Conventional Commits.
35
38
  copilot-agents-optimization: Use when optimizing AGENTS.md or copilot-instructions.md — deduplicates against .augment/ content, enforces line budgets, and focuses each file on its audience.
36
39
  copilot-config: Use when configuring GitHub Copilot — copilot-instructions.md, PR review patterns, output optimization — even when the user just says 'tune Copilot' or 'why is Copilot commenting on X'.
40
+ customer-research: Use when shaping a discovery slice — JTBD-framed interview guide, switch-event focus, verbatim quotes not summaries. Triggers on 'talk to users', 'why did they cancel', 'before we build X'.
37
41
  dashboard-design: Use when designing monitoring dashboards — visualization selection, layout principles, observability strategies (RED/USE/Golden Signals), and data storytelling.
38
42
  data-flow-mapper: Use BEFORE editing code that touches user data — traces the value from entry → validation → transformation → storage → egress, every hop cited with file:line.
39
43
  database: Use when working with database architecture, MariaDB/MySQL tuning, indexing strategies, slow queries, or multi-connection patterns — even when the user just says 'this query is slow'.
40
44
  dcf-modeling: Wing-4 valuation cognition for a CFO / finance-partner. Use when a deal, internal investment, or board ask names DCF, intrinsic value, WACC, terminal value, or 'what's it worth on a 5-year hold'.
45
+ decision-record: Use when locking a trade-off, structuring an ADR draft, or wiring supersession chains — frames options · trade-offs · consequences before the file is written by `adr-create`.
41
46
  deep-reading-analyst: Deep analysis of articles/long-form via thinking frameworks (SCQA, mental models, inversion) — 'analyze article', 'deep dive', 'extract insights', URL/text wanting depth not summary.
42
47
  defense-in-depth: Use when validation needs entry, business-logic, environment, and instrumentation guards so a bad value cannot reach the failure point — turns a local bug fix into a structural one.
43
48
  dependency-upgrade: Use when upgrading dependencies — "update Laravel", "bump PHP version", or "upgrade packages". Covers changelog review, breaking change detection, and verification.
@@ -45,6 +50,7 @@ description-assist: Use when polishing a skill/rule/command/guideline frontmatte
45
50
  design-review: Use when the user says "review the design", "check the UI", or wants a comprehensive UI/UX review. Uses a 7-phase methodology covering interaction, responsiveness, accessibility, and more.
46
51
  devcontainer: Use when configuring DevContainers or GitHub Codespaces — devcontainer.json, custom images, secrets, VS Code features — even when the user just says 'why does my Codespace not start'.
47
52
  developer-like-execution: Use when implementing, debugging, refactoring, or reviewing code — enforces the think → analyze → verify → execute workflow — even when the user just says 'implement X' without naming it.
53
+ discovery-interview: Use when running discovery interviews — question-bank build, bias audit, insight extraction. Triggers on 'audit my guide', 'extract insights from transcript', 'is my hypothesis falsifiable'.
48
54
  docker: Use when working with Docker — Dockerfile edits, docker-compose services, containers, or the dual-container (fast + Xdebug) setup — even when the user just says 'my container won't start'.
49
55
  dto-creator: Use when the user says "create a DTO", "new data transfer object", or needs to convert request/response data into a typed PHP class. Creates DTOs with SimpleDto base class and attribute mapping.
50
56
  eloquent: Use when writing Eloquent models, relationships, scopes, or queries via Model:: — 'fetch users with their orders'. NOT for PHPStan output, non-Eloquent services, or raw SQL questions.
@@ -56,11 +62,13 @@ feature-planning: Use when the user says "plan a feature", "brainstorm", "explor
56
62
  file-editor: Use when opening edited files in the user's IDE. Reads settings from .agent-settings.yml to determine IDE and whether auto-open is enabled.
57
63
  finishing-a-development-branch: Use when the feature is implementation-complete and the next step is 'ship it' — verifies, cleans up, and routes to merge/PR/park/discard — even when the user just says 'I'm done, what now?'.
58
64
  flux: Use when the project uses `livewire/flux` — dispatched by `directives/ui/{apply,review,polish}.py`. Covers Flux components, slots, variants, and form primitives.
65
+ form-handler: Use when designing or reviewing a form — validation timing, error display, submission lifecycle, optimistic UI, dirty/pristine state, idempotency — even on 'why does submit double-fire?'.
59
66
  funnel-analysis: Use when diagnosing where a SaaS or product funnel leaks — visitor → signup → activation → paid → retained — channel-agnostic, conversion-rate-driven.
60
67
  git-workflow: Use when working with Git — branch naming, commit messages, PR creation, rebasing, or the code review process — even when the user says 'push this' or 'merge the branch' without naming Git.
61
68
  github-ci: Use when working with GitHub Actions — workflow YAML, quality gates, test matrices, deployment triggers, reusable workflows — even when the user just says 'my CI is failing' or 'add a check'.
62
69
  grafana: Use when working with Grafana — dashboards, Loki LogQL queries, alerting rules, monitoring panels — even when the user just says 'build me a dashboard' or 'query the logs' without naming Grafana.
63
70
  guideline-writing: Use when creating or editing a guideline in docs/guidelines/ — reference material cited by skills, no auto-triggers — even when the user just says 'write up our naming conventions'.
71
+ incident-commander: Use during or right after an incident — frames severity, sets comms cadence, drafts the post-mortem skeleton — even when the user just says 'production is down' or 'wir haben einen Vorfall'.
64
72
  jira-integration: Use when the user says "check Jira", "create ticket", "update issue", or needs JQL queries, ticket transitions, or branch-to-ticket linking.
65
73
  jobs-events: Use when creating Laravel jobs, queued workflows, events, or listeners. Covers clear responsibilities, safe serialization, and retry/failure handling.
66
74
  judge-bug-hunter: Use when a diff needs correctness review — null-safety, edge cases, off-by-one, races, error handling — dispatched by /review-changes, /do-and-judge, /judge, even without 'judge'.
@@ -77,15 +85,19 @@ laravel-pulse: Use when setting up Laravel Pulse — real-time dashboard, built-
77
85
  laravel-reverb: Use when configuring Laravel Reverb — the first-party WebSocket server with Pusher protocol compatibility, horizontal scaling, and Pulse monitoring.
78
86
  laravel-scheduling: Use when configuring Laravel task scheduling — cron expressions, frequency helpers, overlap prevention, maintenance mode, or output handling.
79
87
  laravel-validation: Use when writing validation — Form Requests, rules, custom rule objects, request-boundary design — even when the user just says 'validate this input' or 'check the request' without naming it.
88
+ launch-readiness: Use before merging a release-shaped PR — pre-merge checklist, rollout plan, rollback criteria, ops handoff. Triggers on 'ready to ship', 'launch checklist', 'rollout plan for X'.
80
89
  learning-to-rule-or-skill: Use when a repeated learning, mistake, or successful pattern should be turned into a new rule or skill. Also use after completing a task to capture learnings from the work.
81
90
  lint-skills: Use when running the package's skill linter against all skills and rules to validate frontmatter, required sections, and execution metadata.
82
91
  livewire: Use when the project's frontend stack is Livewire — dispatched by `directives/ui/{apply,review,polish}.py`. Covers reactive state, events, lifecycle hooks, and component/view separation.
92
+ livewire-architect: Use when shaping a Livewire component before code — full-page vs partial, parent/child split, event flow, state-vs-props boundary, hydration cost — even on 'add this Livewire component'.
83
93
  logging-monitoring: Use when working with logging or monitoring — Sentry error tracking, Grafana/Loki log aggregation, structured logging channels, or monitoring helpers.
84
94
  markitdown: Use when converting PDF, DOCX, XLSX, PPTX, EPUB, images, or audio to Markdown for LLM ingestion via the upstream markitdown-mcp server — 'extract this PDF', 'OCR this image', 'transcribe this audio'.
85
95
  mcp: Use when working with MCP (Model Context Protocol) servers — their tools, capabilities, and best practices for effective agent workflows.
86
96
  mcp-builder: Use when building an MCP server in Python (FastMCP) or Node/TypeScript (MCP SDK) — agent-centric tool design, input schemas, error handling, and the 10-question evaluation harness.
87
97
  md-language-check: Use BEFORE saving any .md under .augment/, .agent-src*/, or agents/ — scans umlauts, German function words, and quoted German phrases outside DE:/EN: anchor blocks. Hard gate per language-and-tone.
98
+ memory-consolidation: Use when consolidating session signals into curated memory — four-phase loop ORIENT → GATHER → CONSOLIDATE → PRUNE. Triggers on 'mine my sessions', 'consolidate memory', 'review intake signals'.
88
99
  merge-conflicts: Use when the user has merge conflicts or says "resolve conflicts". Understands conflict markers, resolution strategies, and verification workflow.
100
+ migration-architect: Use when shaping a non-trivial migration — rollout phases, dual-write windows, cutover sequencing, deprecation cycles — hands off to `migration-creator` for DDL once locked.
89
101
  migration-creator: Use when the user says "create migration", "add column", or "new table". Creates migrations with correct table prefixes, column naming, and multi-tenant awareness.
90
102
  mobile-e2e-strategy: Use when picking a mobile E2E framework — Detox / Appium / Maestro / XCUITest / Espresso — or planning iOS Simulator / Android Emulator coverage in CI for RN, Expo, or native apps.
91
103
  module-management: Use when the user says "create module", "explore module", or works within app/Modules/. Understands module structure, auto-loading, route registration, and namespace conventions.
@@ -100,7 +112,9 @@ pest-testing: Use when writing, generating, or improving Pest tests for Laravel
100
112
  php-coder: Writes or edits PHP code — controllers, classes, type hints, SOLID refactors, modern idioms — even without naming PHP. NOT for writing tests (use pest-testing) or explaining PHP concepts.
101
113
  php-debugging: Use when debugging PHP with Xdebug — breakpoints, step-through, dual-container setup, IDE configuration, header-based routing — even when the user just says 'why does this blow up on request X'.
102
114
  php-service: Use when the user says 'create service', 'new service class', or needs a PHP service following SOLID principles with proper DI and repository usage.
115
+ playwright-architect: Use when shaping a Playwright suite — locator strategy, Page Object boundaries, fixture composition, flake-prevention architecture, CI-vs-local split — even on 'design our E2E tests'.
103
116
  playwright-testing: Use when writing Playwright E2E tests — browser automation, visual regression testing, Page Objects, fixtures, and reliable test patterns.
117
+ po-discovery: Use when shaping a fuzzy product ask into a refined backlog item — problem framing, user-story rewrite, AC tightening — even if the user just says 'help me write this ticket'.
104
118
  project-analysis-core: Use for the universal deep-analysis workflow: project discovery, version resolution, docs loading, architecture mapping, execution flow, and package research.
105
119
  project-analysis-hypothesis-driven: Use when a bug has multiple plausible causes across layers — competing hypotheses, validation loops, evidence-based conclusions — even when the user just says 'why is this happening?'.
106
120
  project-analysis-laravel: Use for deep Laravel project analysis: boot flow, request lifecycle, container usage, Eloquent/data flow, async systems, and Laravel-specific failure patterns.
@@ -122,10 +136,12 @@ readme-writing-package: Use when creating or rewriting a README for a reusable p
122
136
  receiving-code-review: Use when processing code review feedback (bot or human) before changing anything — triages, verifies, and pushes back with technical reasoning — even when the user just says 'fix the comments'.
123
137
  "refine-prompt": Reconstruct a free-form prompt into actionable AC + assumptions + confidence band before the engine plans — '/work \"…\"', 'baue X', 'ist der Prompt klar genug für die Engine?'.
124
138
  "refine-ticket": Refine a Jira/Linear ticket before planning — 'refine ticket', 'tighten AC on PROJ-123', 'ist das Ticket klar?' — rewritten ticket, Top-5 risks, persona voices, sub-skills orchestrated, close-prompt.
139
+ release-comms: Use when turning a shipped changelog into a release narrative — value-not-feature framing, audience-segmented surfaces, one source of truth. Triggers on 'announce the release', 'write changelog post'.
125
140
  repomix-packer: Use when packaging a codebase to a single AI-friendly file for LLM analysis — local or remote, XML/Markdown/JSON, token counting, gitignore filtering, peer-side `repomix` CLI.
126
141
  requesting-code-review: Use when asking for a review or creating a PR — self-review first, frame the right context, test plan included — even when the user just says 'open a PR' or 'ready to merge'.
127
142
  review-routing: Use when preparing a PR description, suggesting reviewers, or flagging risk — produces owner-mapped roles plus historical bug-pattern matches from project-local YAML.
128
143
  rice-prioritization: Use when ranking competing initiatives for a roadmap, breaking a tie between two features, or auditing a backlog for hidden low-value work via Reach × Impact × Confidence ÷ Effort.
144
+ risk-officer: Use when surfacing and prioritising risk before commit — blast-radius framing, mitigations, residual-risk verdict — even if the user just says 'what could go wrong here?'.
129
145
  roadmap-management: Use when the user says "create roadmap", "show roadmap", or "execute roadmap". Creates, reads, and manages roadmap files with phase tracking.
130
146
  roadmap-writing: Use when authoring or rewriting a roadmap in agents/roadmaps/ — phase prose, goal sentence, acceptance criteria, council notes — even when the user just says 'write a plan for X' or 'draft a roadmap'.
131
147
  rtk-output-filtering: Use when running verbose CLI commands — wraps them with rtk (Rust Token Killer) for 60-90% token savings. Covers installation, configuration, and usage patterns.
@@ -141,8 +157,11 @@ skill-management: Use when compressing, decompressing, refactoring, or improving
141
157
  skill-reviewer: Use when reviewing, auditing, or optimizing skills — validates against the 7 Skill Killers checklist and produces fix recommendations.
142
158
  skill-writing: Use when deciding 'should this be a skill or a rule?', creating/improving/reviewing agent skills, SKILL.md frontmatter, or procedure sections — even without saying 'skill-writing'.
143
159
  sql-writing: Use when writing raw SQL — MariaDB/MySQL syntax, parameterization, raw migrations, seeders with `DB::statement` — even when the user just pastes a query and asks 'why is this slow' without naming SQL.
144
- subagent-orchestration: Use when orchestrating implementer/judge subagentssix modes (do-and-judge, do-in-steps, do-in-parallel, do-competitively, judge-with-debate, do-in-worktrees)models from .agent-settings.yml.
160
+ stakeholder-tradeoff: Use when stakeholders pull a decision in different directions frames each lens, builds a trade-off matrix, surfaces the cost of every choice even if the user just says 'PO and ops disagree'.
161
+ subagent-orchestration: Use when orchestrating implementer/judge subagents — seven modes (do-and-judge ±two-stage, do-in-steps/parallel/worktrees, do-competitively, judge-with-debate) — models from .agent-settings.yml.
145
162
  systematic-debugging: Use when hitting a bug, test failure, crash, or unexpected behavior — enforces reproduce → isolate → hypothesize → verify before any fix — even when the user just says 'this is broken' or 'quick fix'.
163
+ tailwind-engineer: Use when writing or reviewing Tailwind CSS — utility-first, design-token discipline, no inline-style drift, responsive variants, dark mode — even on 'style this' or 'mach das hübsch'.
164
+ tech-debt-tracker: Use when surfacing tech debt as trackable items — interest-vs-principal framing, prioritisation by carrying cost, repayment plan — even if the user just says 'this codebase is a mess'.
146
165
  technical-specification: Use when the user says "write a spec", "create RFC", "write a PRD", or "document this decision". Writes technical specifications, PRDs, RFCs, and ADRs with clear structure.
147
166
  terraform: Use when writing Terraform — AWS modules, resources, variables, outputs, remote state — even when the user just says 'provision this infra' or 'add an S3 bucket' without naming Terraform.
148
167
  terragrunt: Use when working with Terragrunt — DRY multi-env configs, module dependencies, remote state orchestration — even when the user just says 'deploy this to staging and prod' without naming Terragrunt.
@@ -152,10 +171,12 @@ testing-anti-patterns: Use BEFORE writing or changing tests, adding mocks, or pu
152
171
  threat-modeling: Use when adding auth, webhooks, uploads, queues, secrets, tenant boundaries, or public endpoints — produces trust boundaries + abuse cases mapped to files, BEFORE implementation.
153
172
  token-optimizer: Use BEFORE any verbose CLI run, large file read, doc conversion, or near-context handoff — single decision tree keyed by intent that cites the canonical token-saving asset. Consult before the action.
154
173
  traefik: Use when setting up Traefik as a local reverse proxy — real domains on 127.0.0.1, trusted HTTPS via mkcert, automatic service discovery, and multi-project routing.
174
+ ui-component-architect: Use when shaping a UI component tree — composition vs inheritance, slot patterns, prop API design, controlled vs uncontrolled, polymorphic — even on 'split this component'.
155
175
  unit-economics-modeling: Use when modeling CAC, LTV, gross-margin payback, or contribution margin per customer — for SaaS, marketplace, or transactional businesses.
156
176
  universal-project-analysis: ONLY when user explicitly requests: full project analysis, deep codebase audit, or comprehensive architecture review. Routes to core and framework-specific analysis skills.
157
177
  upstream-contribute: Use when a learning, new skill, rule improvement, or bug fix from a consumer project should be contributed back to the shared agent-config package.
158
178
  using-git-worktrees: Use when starting parallel work in isolation from the current branch — spawn a git worktree with ignore-safety checks and a clean test baseline — even when the user says 'try this on the side'.
159
179
  "validate-feature-fit": Validate whether a feature request fits the existing codebase — check for duplicates, contradictions, scope creep, and architectural misfit
160
180
  verify-completion-evidence: Use when claiming 'done', suggesting a commit, push, or PR — runs the evidence gate so completion claims come from fresh output in this message, not memory or earlier runs.
181
+ voc-extract: Use when extracting Voice-of-Customer themes from existing artefacts — GH issues, PR threads, Sentry patterns. Triggers on 'what are users saying', 'recurring complaints', 'top themes'.
161
182
  websocket: Use when building real-time features — WebSocket broadcasting, live updates, presence channels, connection state — even when the user just says 'push this to the client live'.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Shared agent configuration \u2014 skills, rules, commands, guidelines, and templates for AI coding tools",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -0,0 +1,157 @@
1
+ """``agent-config export`` — eject a tool's canonical content into the project.
2
+
3
+ Phase 1.5 of road-to-global-first-install.md (ADR-007 D3). Replaces the
4
+ rejected symlink-bridge subcommand: writes a real file with the resolved
5
+ content for a named tool into a user-chosen path so it can be committed,
6
+ shared with the team, or customized in place. Idempotent by default;
7
+ ``--force`` overrides content drift. No canonical-path defaults.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import hashlib
13
+ import sys
14
+ from pathlib import Path
15
+ from typing import Callable, Optional
16
+
17
+ from scripts.install import (
18
+ AIDER_MARKER,
19
+ CLAUDE_DESKTOP_MARKER,
20
+ CODEX_MARKER,
21
+ CONTINUE_MARKER,
22
+ JETBRAINS_MARKER,
23
+ KILOCODE_MARKER,
24
+ KIRO_MARKER,
25
+ ROOCODE_MARKER,
26
+ ZED_MARKER,
27
+ )
28
+
29
+ PACKAGE_ROOT = Path(__file__).resolve().parents[2]
30
+ TEMPLATES_DIR = PACKAGE_ROOT / ".agent-src" / "templates"
31
+
32
+
33
+ def _from_template(rel: str) -> Callable[[], str]:
34
+ def _read() -> str:
35
+ path = TEMPLATES_DIR / rel
36
+ if not path.is_file():
37
+ raise FileNotFoundError(
38
+ f"template missing from package: {path} "
39
+ f"(reinstall @event4u/agent-config or report a bug)"
40
+ )
41
+ return path.read_text(encoding="utf-8")
42
+ return _read
43
+
44
+
45
+ def _from_constant(value: str) -> Callable[[], str]:
46
+ def _read() -> str:
47
+ return value
48
+ return _read
49
+
50
+
51
+ # tool_id → (description, content_provider).
52
+ EXPORT_REGISTRY: "dict[str, tuple[str, Callable[[], str]]]" = {
53
+ "roocode": ("Roo Code marker (.roo/rules/agent-config.md body)",
54
+ _from_constant(ROOCODE_MARKER)),
55
+ "claude-desktop": ("Claude Desktop marker (informational, global-scope tool)",
56
+ _from_constant(CLAUDE_DESKTOP_MARKER)),
57
+ "aider": ("Aider marker (manual `read:` wiring documented inline)",
58
+ _from_constant(AIDER_MARKER)),
59
+ "codex": ("Codex CLI marker (informational — AGENTS.md is canonical)",
60
+ _from_constant(CODEX_MARKER)),
61
+ "continue": ("Continue.dev marker (.continue/rules/agent-config.md body)",
62
+ _from_constant(CONTINUE_MARKER)),
63
+ "kilocode": ("Kilo Code marker (.kilocode/rules/agent-config.md body)",
64
+ _from_constant(KILOCODE_MARKER)),
65
+ "zed": ("Zed marker (informational — .rules at repo root is canonical)",
66
+ _from_constant(ZED_MARKER)),
67
+ "jetbrains": ("JetBrains AI Assistant marker (.jetbrains/agent-config.md body)",
68
+ _from_constant(JETBRAINS_MARKER)),
69
+ "kiro": ("Kiro marker (.kiro/steering/agent-config.md body)",
70
+ _from_constant(KIRO_MARKER)),
71
+ "agents-md": ("AGENTS.md template (Thin-Root entry point — consumer scaffold)",
72
+ _from_template("AGENTS.md")),
73
+ "copilot-instructions": ("GitHub Copilot Code Review instructions template",
74
+ _from_template("copilot-instructions.md")),
75
+ }
76
+
77
+
78
+ def _list_tools(out) -> int:
79
+ print("Available tools for `agent-config export --tool <id>`:", file=out)
80
+ width = max(len(t) for t in EXPORT_REGISTRY) + 2
81
+ for tool_id, (desc, _) in sorted(EXPORT_REGISTRY.items()):
82
+ print(f" {tool_id:<{width}}{desc}", file=out)
83
+ return 0
84
+
85
+
86
+ def _hash(content: str) -> str:
87
+ return hashlib.sha256(content.encode("utf-8")).hexdigest()
88
+
89
+
90
+ def _rel(path: Path) -> Path:
91
+ try:
92
+ return path.relative_to(Path.cwd())
93
+ except ValueError:
94
+ return path
95
+
96
+
97
+ def _write(output: Path, content: str, *, force: bool, out, err) -> int:
98
+ if output.exists():
99
+ existing = output.read_text(encoding="utf-8")
100
+ if _hash(existing) == _hash(content):
101
+ print(f"ℹ️ {_rel(output)} already exported (content matches).", file=out)
102
+ return 0
103
+ if not force:
104
+ print(
105
+ f"❌ refusing to overwrite {output} — content differs. "
106
+ f"Pass --force to replace.",
107
+ file=err,
108
+ )
109
+ return 1
110
+ output.parent.mkdir(parents=True, exist_ok=True)
111
+ output.write_text(content, encoding="utf-8")
112
+ print(f"✅ exported to {_rel(output)}", file=out)
113
+ return 0
114
+
115
+
116
+ def main(argv: Optional[list[str]] = None, *, out=sys.stdout, err=sys.stderr) -> int:
117
+ parser = argparse.ArgumentParser(
118
+ prog="agent-config export",
119
+ description="Eject a tool's resolved content into a user-chosen path.",
120
+ )
121
+ parser.add_argument("--tool", metavar="ID",
122
+ help="Tool to export (see --list for the catalog).")
123
+ parser.add_argument("--output", metavar="PATH",
124
+ help="Destination path (relative to CWD).")
125
+ parser.add_argument("--force", action="store_true",
126
+ help="Overwrite an existing file with non-matching content.")
127
+ parser.add_argument("--list", action="store_true",
128
+ help="Print supported tool IDs with descriptions and exit.")
129
+ args = parser.parse_args(argv)
130
+
131
+ if args.list:
132
+ return _list_tools(out)
133
+ if not args.tool:
134
+ print("❌ --tool is required (see --list for the catalog).", file=err)
135
+ return 2
136
+ if not args.output:
137
+ print("❌ --output is required (no canonical-path defaults).", file=err)
138
+ return 2
139
+
140
+ entry = EXPORT_REGISTRY.get(args.tool)
141
+ if entry is None:
142
+ print(f"❌ unknown tool: {args.tool} (see --list)", file=err)
143
+ return 2
144
+
145
+ _, provider = entry
146
+ try:
147
+ content = provider()
148
+ except FileNotFoundError as exc:
149
+ print(f"❌ {exc}", file=err)
150
+ return 1
151
+
152
+ output = Path(args.output).expanduser().resolve()
153
+ return _write(output, content, force=args.force, out=out, err=err)
154
+
155
+
156
+ if __name__ == "__main__": # pragma: no cover
157
+ sys.exit(main())
@@ -0,0 +1,162 @@
1
+ """``agent-config sync`` — replay the installed-tools manifest (ADR-008).
2
+
3
+ Phase 3.3 of road-to-global-first-install.md. Reads
4
+ ``agents/installed-tools.lock``, then re-runs the bridge install for every
5
+ tool whose ``bridge_marker`` is missing on disk. Tools whose marker already
6
+ exists are skipped — the typical clone-and-sync flow is therefore idempotent
7
+ on the second invocation.
8
+
9
+ Sync never edits the manifest itself; ``init`` is the only writer. Sync only
10
+ calls the installer with ``--scope`` / ``--tools`` derived from the manifest
11
+ entries, so the manifest is the single source of truth.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import os
17
+ import sys
18
+ from pathlib import Path
19
+ from typing import Iterable
20
+
21
+ from scripts._lib import installed_tools
22
+ from scripts.install import main as install_main
23
+
24
+
25
+ def _marker_exists(project_root: Path, bridge_marker: str, scope: str) -> bool:
26
+ if not bridge_marker:
27
+ return True # substrate-only entries (rare); treat as present
28
+ if scope == "global":
29
+ target = Path(bridge_marker).expanduser()
30
+ else:
31
+ # Project-scope: relative to the project root unless absolute.
32
+ candidate = Path(bridge_marker)
33
+ target = candidate if candidate.is_absolute() else (project_root / candidate)
34
+ return target.exists()
35
+
36
+
37
+ def _group_by_scope(
38
+ entries: Iterable[dict],
39
+ project_root: Path,
40
+ ) -> tuple[dict[str, list[str]], list[tuple[str, str]]]:
41
+ """Return ({scope: [tool_names]}, [(name, marker_path)]) for missing tools.
42
+
43
+ The second list is the human-readable summary of what will be replayed.
44
+ """
45
+ missing: dict[str, list[str]] = {"project": [], "global": []}
46
+ surfaced: list[tuple[str, str]] = []
47
+ for entry in entries:
48
+ name = str(entry.get("name", "")).strip()
49
+ scope = str(entry.get("scope", "")).strip()
50
+ bridge_marker = str(entry.get("bridge_marker", "")).strip()
51
+ if not name or scope not in ("project", "global"):
52
+ continue
53
+ if _marker_exists(project_root, bridge_marker, scope):
54
+ continue
55
+ missing[scope].append(name)
56
+ surfaced.append((name, bridge_marker))
57
+ return missing, surfaced
58
+
59
+
60
+ def _run_install(scope: str, tools: list[str], project_root: Path, *, force: bool, dry_run: bool) -> int:
61
+ if not tools:
62
+ return 0
63
+ argv = [f"--scope={scope}", f"--tools={','.join(sorted(set(tools)))}"]
64
+ if scope == "project":
65
+ argv += [f"--project={project_root}", "--no-smoke"]
66
+ if force:
67
+ argv.append("--force")
68
+ if dry_run:
69
+ argv.append("--skip-bridges")
70
+ return install_main(argv)
71
+
72
+
73
+ def _parse(argv: list[str]) -> argparse.Namespace:
74
+ parser = argparse.ArgumentParser(
75
+ prog="agent-config sync",
76
+ description=(
77
+ "Replay agents/installed-tools.lock — re-installs any tool whose "
78
+ "bridge marker is missing locally. Idempotent."
79
+ ),
80
+ )
81
+ parser.add_argument(
82
+ "--project",
83
+ default=None,
84
+ help="Override the project root (defaults to PROJECT_ROOT or cwd).",
85
+ )
86
+ parser.add_argument(
87
+ "--dry-run",
88
+ action="store_true",
89
+ help="Print the planned replay set without touching bridges.",
90
+ )
91
+ parser.add_argument(
92
+ "--force",
93
+ action="store_true",
94
+ help="Forwarded to the installer (overwrites existing bridge files).",
95
+ )
96
+ parser.add_argument(
97
+ "--quiet",
98
+ action="store_true",
99
+ help="Suppress non-essential output.",
100
+ )
101
+ return parser.parse_args(argv)
102
+
103
+
104
+ def _emit(quiet: bool, msg: str) -> None:
105
+ if not quiet:
106
+ print(msg)
107
+
108
+
109
+ def main(argv: list[str]) -> int:
110
+ opts = _parse(argv)
111
+ project_root = Path(
112
+ opts.project or os.environ.get("PROJECT_ROOT") or os.getcwd()
113
+ ).resolve()
114
+ manifest = installed_tools.manifest_path(project_root)
115
+ data = installed_tools.read_manifest(manifest)
116
+
117
+ if data is None:
118
+ _emit(opts.quiet, f"❌ No manifest found at {manifest}")
119
+ _emit(opts.quiet, " Run `./agent-config init --tools=<id>` to create one.")
120
+ return 1
121
+
122
+ entries = list(data.get("tools") or [])
123
+ if not entries:
124
+ _emit(opts.quiet, f"ℹ️ Manifest is empty: {manifest}")
125
+ return 0
126
+
127
+ missing, surfaced = _group_by_scope(entries, project_root)
128
+ total_missing = sum(len(v) for v in missing.values())
129
+ total_present = len(entries) - total_missing
130
+
131
+ _emit(opts.quiet, f"Manifest: {manifest}")
132
+ _emit(opts.quiet, f"Tools: {len(entries)} listed, {total_present} present, {total_missing} missing")
133
+ if total_missing == 0:
134
+ _emit(opts.quiet, "✅ All bridges already installed. Nothing to do.")
135
+ return 0
136
+
137
+ for name, marker in surfaced:
138
+ _emit(opts.quiet, f" • {name:<15} → {marker} (missing)")
139
+
140
+ if opts.dry_run:
141
+ _emit(opts.quiet, "")
142
+ _emit(opts.quiet, "Dry-run: no bridges written.")
143
+ return 0
144
+
145
+ _emit(opts.quiet, "")
146
+ for scope in ("project", "global"):
147
+ tools = missing[scope]
148
+ if not tools:
149
+ continue
150
+ _emit(opts.quiet, f"Replaying scope={scope}: {', '.join(sorted(tools))}")
151
+ rc = _run_install(scope, tools, project_root, force=opts.force, dry_run=False)
152
+ if rc != 0:
153
+ _emit(opts.quiet, f"❌ Installer failed for scope={scope} (rc={rc}); aborting.")
154
+ return rc
155
+
156
+ _emit(opts.quiet, "")
157
+ _emit(opts.quiet, "✅ Sync complete.")
158
+ return 0
159
+
160
+
161
+ if __name__ == "__main__":
162
+ sys.exit(main(sys.argv[1:]))
@@ -36,7 +36,7 @@ from datetime import datetime, timezone
36
36
  from pathlib import Path
37
37
  from typing import Optional
38
38
 
39
- from scripts._lib import update_check
39
+ from scripts._lib import installed_lock, update_check
40
40
  from scripts._lib.agent_settings import (
41
41
  DEFAULT_PROJECT_FILE,
42
42
  _resolve_cascade_paths,
@@ -205,9 +205,31 @@ def main(
205
205
 
206
206
  cache_warmer(latest)
207
207
  _refresh_state(latest, latest, state_path)
208
+ _refresh_global_lockfile(latest, out=out)
208
209
  return 0
209
210
 
210
211
 
212
+ def _refresh_global_lockfile(version: str, *, out=sys.stdout) -> None:
213
+ """Update ``~/.config/agent-config/installed.lock`` if it exists.
214
+
215
+ Phase 1.6 — the lockfile is only present when the user has run a
216
+ global install; we never create one here, but we keep it in lockstep
217
+ when ``update`` flips the pin. Atomic write goes through
218
+ ``installed_lock.write_lockfile``.
219
+ """
220
+ lock_path = installed_lock.lockfile_path()
221
+ existing = installed_lock.read_lockfile(path=lock_path)
222
+ if existing is None:
223
+ return
224
+ recorded = existing.get("agent_config_version")
225
+ tools = list(existing.get("tools", []))
226
+ if recorded == version:
227
+ print(f"ℹ️ {lock_path} already records {version}.", file=out)
228
+ return
229
+ installed_lock.write_lockfile(version, tools, path=lock_path)
230
+ print(f"✅ Refreshed global lockfile at {lock_path}.", file=out)
231
+
232
+
211
233
  def _detect_installed_version() -> str:
212
234
  """Read ``version`` from the package's own ``package.json``."""
213
235
  pkg_json = Path(__file__).resolve().parents[2] / "package.json"