You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Final pass after the technical-writer review caught 3 must-fix
contradictions/omissions and 6 polish items.
Must-fix
* README claimed glob matching was 'case-insensitive' — directly
contradicting both the code (custom regex without /i) and the test
suite. The wrong claim also undermined the security rationale.
Replaced with the correct case-sensitive description.
* composer skills:list-trust was undocumented in README and CHANGELOG
despite shipping in this PR. Added to both, with a description of
what it shows.
* The README's per-package prompt example was stale — missing the [?]
help option, the 'change later: composer skills:trust …' recovery
hint, and using the wrong [d] description. Synced with the actual
prompt text.
Should-fix
* docs/PRD.md addendum still described the 'composer config --json'
hint and the auto-seeding-everything behaviour, both replaced in
earlier commits. Rewrote that subsection to match the current
first-run policy and added the four-command inventory table.
* README 'Upgrading from v0.1.x' listed [a]/[d]/[n] options in inverse
order vs the prompt's [n,d,a]. Reordered for visual consistency.
* examples/database-analyzer-skill/README.md treated 'type:
ai-agent-skill' as the only discovery mechanism. Added a top-of-file
note pointing to the library-bundled-skill alternative, and updated
the troubleshooting line to reference composer skills:trust.
Nice-to-have
* TrustDecision had no class docblock; mirrored TrustState's docblock
and explained the distinction so maintainers see it from both sides.
* README Quick Start step 2 'Skills Auto-Register' didn't mention the
trust prompt; users would be surprised when their install paused.
Added one bullet pointing at the Trust Model section.
* CHANGELOG entry for the [?] help loop in the per-package prompt.
127 tests / 464 assertions still green. PHPStan level 10 clean.
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
28
28
-**Root package is auto-trusted** — projects that ship their own `SKILL.md` no longer get prompted to authorize themselves.
29
29
-`composer list-skills` now shows trust state (`[allowed]` / `[pending]` / `[denied]`) per skill and a footer count of pending packages. The command is purely informational and never prompts.
30
30
-`composer skills:trust <package>` command — allow (`composer skills:trust vendor/foo`), deny (`--deny`), or revoke (`--revoke`) a trust decision without hand-editing `composer.json`. Used as the recovery path for accidental denies and as the canonical fix for non-interactive failures.
31
+
-`composer skills:list-trust` command — read-only inventory of every persisted decision in `extra.ai-agent-skill.allow-skills`, with `[allowed]` / `[denied]` and `(exact)` / `(glob)` markers per entry. Companion to `skills:trust`; never prompts, never mutates.
32
+
- Trust prompt mirrors Composer's plugin prompt shape (`y`/`n`/`a`/`d`/`?`). The `?` answer shows per-option help and re-prompts. The prompt also includes an inline `composer skills:trust <package>` recovery hint so users have an on-screen breadcrumb if they pick `n` by accident.
31
33
-`composer read-skill` now shows trust state in the header and warns when reading content from a pending or denied skill (which is not registered in `AGENTS.md`).
32
34
-`SkillTrustManager`, `PackageProvider`, `InstalledVersionsProvider`, `PackageInfo`, and `TrustDecision` abstractions for testability.
composer skills:trust vendor/foo --revoke # remove from the map (re-prompts next install)
137
+
composer skills:list-trust # show every persisted decision
134
138
```
135
139
136
140
Or edit `composer.json` directly. Glob patterns (`vendor/*`) are supported.
137
141
138
-
> ⚠️ **Glob matching is case-insensitive and `*` matches any characters.** A pattern like `acme/skills-*` also trusts `acme/skills-anything-else` — use globs only for namespaces you fully control. A typo like `acme/sk*` would match a wide range of unrelated packages. Prefer explicit per-package entries when in doubt.
142
+
> ⚠️ **Glob matching is case-sensitive and `*` matches any characters within a pattern segment.**Composer normalizes published package names to lowercase, so write trust patterns in lowercase. A pattern like `acme/skills-*` also trusts `acme/skills-anything-else` — use globs only for namespaces you fully control. Exact-string keys always override matching globs, even when the glob was added first. Prefer explicit per-package entries when in doubt.
139
143
140
144
In non-interactive mode (`composer install --no-interaction`, CI), packages without an explicit decision are skipped with a warning — the plugin never auto-trusts on your behalf. The warning suggests `composer skills:trust <package>` so CI failures are one command away from a fix. `composer list-skills` shows the trust state per skill (`[allowed]` / `[pending]` / `[denied]`) without firing prompts.
141
145
142
146
### Upgrading from v0.1.x
143
147
144
148
If you upgrade from v0.1.x with `type: ai-agent-skill` packages already installed, the first install/update after the upgrade triggers a one-time prompt asking how to seed the trust map. Choose:
145
149
146
-
-**`[a]`** to keep the v0.1.x default (every existing skill package auto-trusted) — fastest, widest trust surface.
147
-
-**`[d]`** to auto-trust only the dedicated skill packages your root `composer.json` directly requires; transitive ones still prompt per-package.
148
150
-**`[n]`** (default) to auto-trust nothing — every package goes through the per-package prompt during the same install.
151
+
-**`[d]`** to auto-trust only the dedicated skill packages your root `composer.json` directly requires; transitive ones still prompt per-package.
152
+
-**`[a]`** to keep the v0.1.x default (every existing skill package auto-trusted) — fastest, widest trust surface.
149
153
150
154
Non-interactive runs (`--no-interaction`, CI) default to `[n]` with a `composer skills:trust <package>` recovery line per affected package.
Copy file name to clipboardExpand all lines: docs/PRD.md
+24-5Lines changed: 24 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -867,14 +867,33 @@ Discovery now iterates **all** installed packages and selects those that either:
867
867
868
868
Broadening discovery means any transitive dependency could potentially register skills. To keep the security story intact, the plugin requires per-package opt-in before reading SKILL.md content for inclusion in `AGENTS.md` — the same shape Composer uses for `allow-plugins`:
869
869
870
-
-**Interactive mode**: `[y,n,a,d]` prompt; `y`/`n` persist to `composer.json`, `a` is session-only, `d`discards.
871
-
-**Non-interactive mode**: skip with a `composer config --json` hint (gentler than Composer's hard-fail; CI stays deterministic).
872
-
-**Persistence**: `extra.ai-agent-skill.allow-skills` in the root `composer.json`. Glob patterns (`vendor/*`) supported via `BasePackage::packageNameToRegexp()`.
870
+
-**Interactive mode**: `[y,n,a,d,?]` prompt; `y`/`n` persist to `composer.json`, `a` is session-only, `d`leaves undecided (re-prompts next run), `?` shows per-option help and re-prompts. The prompt embeds an inline `composer skills:trust …` recovery hint.
871
+
-**Non-interactive mode**: skip with a `composer skills:trust <package>` hint (gentler than Composer's hard-fail; CI stays deterministic).
872
+
-**Persistence**: `extra.ai-agent-skill.allow-skills` in the root `composer.json`. Atomic write via temp file + rename, with a sidecar `flock` file for cross-process safety. Glob patterns (`vendor/*`) supported via a case-sensitive matcher (Composer's `BasePackage::packageNameToRegexp()` always sets `/i`, which we deliberately don't use).
873
873
-**Boundary**: only `SkillPlugin::updateAgentsMd()` — the install/update event handler — invokes `SkillTrustManager::decide()`. Discovery and reporting never prompt.
874
874
875
-
### Auto-seeding for upgrades
875
+
### First-run policy (replaces auto-seeding)
876
876
877
-
To prevent a re-prompt avalanche when existing users upgrade, the plugin auto-seeds the `allow-skills` map on first run with the currently-installed `type: ai-agent-skill` packages. The user already chose to `composer require` those packages — implicit trust. Auto-seeding is a one-shot operation (skipped if the map already exists).
877
+
When `extra.ai-agent-skill.allow-skills` is absent and the project has installed `type: ai-agent-skill` packages, a one-time prompt asks how to seed:
878
+
879
+
-`[n] None` (default, strict) — every package goes through the per-package prompt.
880
+
-`[d] Direct dependencies only` — auto-trust packages your root `composer.json` directly requires; transitives still prompt.
881
+
-`[a] All` — auto-trust every existing skill package. Restores the v0.1.x behaviour at the user's explicit consent.
882
+
883
+
Non-interactive mode defaults to `[n]` and emits a `composer skills:trust …` recovery hint per affected package, marked `(in your require)` or `(pulled in by another package)`. The map is always written (possibly empty) so this prompt fires at most once per project.
884
+
885
+
The earlier prototype's blanket auto-seeding was replaced after the security review flagged it HIGH: a transitive dependency the user never knowingly chose got trust by default. Deny-by-default closes that vector while still allowing a single keystroke (`a`) to keep v0.1.x behaviour for users who want it.
886
+
887
+
### Commands
888
+
889
+
The plugin registers four Composer commands:
890
+
891
+
| Command | Purpose | Mutates? |
892
+
|---|---|---|
893
+
|`composer list-skills`| List every discovered skill with trust state | No |
894
+
|`composer read-skill <name>`| Print full SKILL.md content for one skill | No |
895
+
|`composer skills:trust <package> [--deny\|--revoke]`| Persist a trust decision without prompting | Yes |
896
+
|`composer skills:list-trust`| Show every persisted decision in the allow-skills map | No |
Copy file name to clipboardExpand all lines: examples/database-analyzer-skill/README.md
+5-2Lines changed: 5 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,8 @@
2
2
3
3
This is a reference implementation of an AI agent skill package for the Composer AI Agent Skill Plugin.
4
4
5
+
> **Note:** this example uses `type: ai-agent-skill` — the *dedicated skill package* pattern. Since v0.2.0, any package can ship a skill alongside its primary purpose by adding `extra.ai-agent-skill` to its `composer.json`, regardless of `type`. See the plugin's [README "Creating Skill Packages"](../../README.md#creating-skill-packages) for both patterns. Use this dedicated pattern when the package's only purpose is shipping skills; use the library-bundled pattern when adding a skill to an existing library.
6
+
5
7
## Package Structure
6
8
7
9
```
@@ -50,7 +52,8 @@ description: What it does and when to use it (max 1024 chars)
50
52
## How It Works
51
53
52
54
1.**Installation**: User installs this package via Composer
53
-
2.**Discovery**: Plugin detects `type: ai-agent-skill` during install/update
55
+
2.**Discovery**: Plugin detects `type: ai-agent-skill` (or `extra.ai-agent-skill`) during install/update
56
+
2a. **Trust prompt**: First time a new package's skills appear, the plugin asks the user to allow or deny — see the main README for details
54
57
3.**Registration**: Plugin parses SKILL.md and registers in AGENTS.md
55
58
4.**Usage**: AI agents discover skill via AGENTS.md XML index
1.**Skill not found**: Check `type: ai-agent-skill` in composer.json
234
+
1.**Skill not found**: Check `type: ai-agent-skill`(or `extra.ai-agent-skill`) in composer.json. If the package shows in `composer list-skills` as `[pending]` or `[denied]`, run `composer skills:trust <package>` to allow it.
232
235
2.**Invalid frontmatter**: Validate YAML syntax and required fields
233
236
3.**Wrong name format**: Use only lowercase, numbers, and hyphens
234
237
4.**Description too long**: Keep under 1024 characters
0 commit comments