agentsmesh 0.28.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +64 -11
- package/dist/canonical.d.ts +2 -2
- package/dist/canonical.js +91 -13
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +223 -199
- package/dist/engine.d.ts +2 -2
- package/dist/engine.js +113 -17
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +235 -49
- package/dist/index.js.map +1 -1
- package/dist/{init-B0aI-g8W.d.ts → init-PvpXanVd.d.ts} +17 -3
- package/dist/lessons.d.ts +2 -2
- package/dist/lessons.js +195 -40
- package/dist/lessons.js.map +1 -1
- package/dist/{schema-CzaoYJlG.d.ts → schema-CH_JJep8.d.ts} +5 -0
- package/dist/{target-descriptor-ItDY3NR0.d.ts → target-descriptor-CaLUz7SR.d.ts} +1 -1
- package/dist/targets.d.ts +3 -3
- package/dist/targets.js +28 -9
- package/dist/targets.js.map +1 -1
- package/package.json +1 -1
- package/schemas/agentsmesh.json +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.30.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7b795b8: Lessons: measure effectiveness and sharpen recall
|
|
8
|
+
|
|
9
|
+
The lessons subsystem now tracks whether a recalled rule actually prevented the repeat, and improves recall precision — all opt-in and backward-compatible (no change to the CLI, MCP, or `lessons.json` surface):
|
|
10
|
+
- **Effectiveness signal (opt-in via `AGENTSMESH_LESSONS_TELEMETRY=1`).** An append-only outcome log records deliveries and failures; effectiveness is derived at read time — did a delivered lesson prevent the repeat? Recall **down-ranks** a lesson that fired but never helped, `lessons validate` gains advisory `INEFFECTIVE_LESSON` and `UNCOVERED_FAILURE` findings, and `lessons stats` gains a coarse **effectiveness block** (deliveries, held rate, ineffective count). The signal is deliberately coarse and labeled as such — never presented as proof of prevention.
|
|
11
|
+
- **Diff-aware recall.** The recall hook binds on the content being written, not just the file path, so a keyword lesson can fire on the change itself.
|
|
12
|
+
- **camelCase keyword reach.** Keyword recall now also splits camelCase/acronym identifier sub-words while retaining the whole token (fully backward compatible), so a keyword like `guard` reaches `useLeaveGuard.ts`.
|
|
13
|
+
- **Quieter injection.** Automatic recall caps the injected set to the most relevant few and stays silent on no match.
|
|
14
|
+
- **Recurrence-driven capture nudge.** A failure recurring on the same action with no covering lesson escalates the capture reminder, pre-filled from the real file/command.
|
|
15
|
+
- **Portable failure detection.** The recall hook records a failure from any tool event carrying an error payload, not only Claude Code's dedicated `PostToolUseFailure` event — so effectiveness can accumulate on more harnesses.
|
|
16
|
+
- **New capture warning `WIDE_GLOB_MATCH`** flags a `file_glob` that matches a large share of the working tree, complementing the existing structural broad-glob check.
|
|
17
|
+
- **`agentsmesh init --lessons`** now commits the `.gitattributes` binding for the `lessons.json` union merge driver and prints the per-clone `git config` setup, so a team's concurrent captures merge cleanly instead of conflicting.
|
|
18
|
+
|
|
19
|
+
- 7b795b8: Lessons: `--scope always` for universal always-on rules
|
|
20
|
+
|
|
21
|
+
A lesson can now be captured with `--scope always` (MCP: `scope: "always"`) for a universal standard that applies to every task — a comment/test/style convention that no single file or command names. Always-on lessons need no trigger and are delivered on every task automatically, alongside triggered recall, deduplicated once per session.
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 13730ca: Lint no longer warns about agentsmesh-injected best-effort hook events
|
|
26
|
+
|
|
27
|
+
`agentsmesh lint` previously flagged the recall/capture hook events agentsmesh itself injects (`UserPromptSubmit`, `PostToolUseFailure`, `SessionStart`) as "unsupported" on targets whose hook model can't represent them — an unactionable warning, since agentsmesh injects those events and degrades them gracefully. They are now excluded from the unsupported-hook warning across every whitelist-style target.
|
|
28
|
+
|
|
29
|
+
## 0.29.0
|
|
30
|
+
|
|
31
|
+
### Minor Changes
|
|
32
|
+
|
|
33
|
+
- 663f0e6: Strip elevated artifacts from remote `extends` sources by default
|
|
34
|
+
|
|
35
|
+
`hooks`, `permissions`, and `mcp` contributed by a **remote** `extends` source (`github:`, `gitlab:`, `git+…`, including `git+file://`) are now stripped during config load unless the entry opts in with `accept: [hooks, permissions, mcp]`. This closes a gap where a remote `extends` could inject shell-executing config (settings hooks, MCP launch specs) without the per-artifact consent that `agentsmesh install` already requires. Local `extends` remain trusted as-is, and a warning reports anything that was stripped.
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- 11f90bc: Harden plugin source containment against intermediate-symlink escapes
|
|
40
|
+
|
|
41
|
+
The plugin loader now canonicalizes an unresolvable source path against its nearest existing ancestor instead of falling back to the raw path. This closes a gap where a local plugin `source` routed through a symlinked directory that resolves outside the project root could slip past the trust-boundary check when its entry file did not exist yet. Legitimate in-project plugins are unaffected.
|
|
42
|
+
|
|
43
|
+
- c647c9b: Docs: the README now leads with lessons (the shared agent memory), adds a head-to-head comparison with Ruler and rulesync, embeds demo GIFs, leads the quickstart with the import-first path for existing repos, and documents the new `extends` `accept:` consent. Documentation-only — no behavior change.
|
|
44
|
+
|
|
3
45
|
## 0.28.0
|
|
4
46
|
|
|
5
47
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
# AgentsMesh
|
|
3
|
+
# AgentsMesh
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### One source for every AI coding tool — with a shared agent memory that learns from your repo.
|
|
6
|
+
|
|
7
|
+
<img src="https://raw.githubusercontent.com/sampleXbro/agentsmesh/master/assets/agentsmesh-banner.jpeg" alt="AgentsMesh — One source. Every AI coding tool. Agents that learn." width="100%" />
|
|
6
8
|
|
|
7
9
|
[](https://github.com/sampleXbro/agentsmesh/actions/workflows/ci.yml)
|
|
8
10
|
[](https://www.npmjs.com/package/agentsmesh)
|
|
@@ -23,6 +25,28 @@ Every AI coding assistant has its own config format — `CLAUDE.md`, `AGENTS.md`
|
|
|
23
25
|
> [!NOTE]
|
|
24
26
|
> Full documentation, guides, and the per-tool reference live at **[samplexbro.github.io/agentsmesh](https://samplexbro.github.io/agentsmesh/)**.
|
|
25
27
|
|
|
28
|
+
## How AgentsMesh compares
|
|
29
|
+
|
|
30
|
+
Most config tools stop at copying rule files into each assistant's folder. AgentsMesh is the only one that also gives your agents a **shared memory that learns**, round-trips **losslessly** in both directions, and lets anyone **add a new tool as a plugin** — no release required.
|
|
31
|
+
|
|
32
|
+
| Capability | AgentsMesh | [Ruler](https://github.com/intellectronica/ruler) | [rulesync](https://github.com/dyoshikawa/rulesync) |
|
|
33
|
+
|---|:---:|:---:|:---:|
|
|
34
|
+
| Generate native config for many tools | ✅ | ✅ | ✅ |
|
|
35
|
+
| Import existing tool config back to source | ✅ | — | ✅ |
|
|
36
|
+
| **Lossless round-trip** (re-import restores originals) | ✅ | — | partial |
|
|
37
|
+
| Convert one tool's config directly to another | ✅ | — | ✅ |
|
|
38
|
+
| **Automatic cross-tool link rebasing** | ✅ | — | — |
|
|
39
|
+
| **Lessons — a shared agent memory that learns** | ✅ | — | — |
|
|
40
|
+
| **Plugins — add a target without a release** | ✅ | — | — |
|
|
41
|
+
| Cross-target lint (warn before silent data loss) | ✅ | — | — |
|
|
42
|
+
| CI drift gate + git-merge recovery | ✅ | partial | partial |
|
|
43
|
+
| Self-serve MCP server (agent-operable config) | ✅ | — | — |
|
|
44
|
+
| `--json` everywhere + typed programmatic API | ✅ | — | partial |
|
|
45
|
+
|
|
46
|
+
<sub>Reflects the public projects as of June 2026 — see the [alternatives guide](https://samplexbro.github.io/agentsmesh/reference/alternatives/) for sources and detail. Corrections welcome.</sub>
|
|
47
|
+
|
|
48
|
+
Built to be depended on: **8,000+ tests** run on Linux, macOS, and Windows CI (Node 22 & 24), configs are JSON-Schema-validated, npm releases ship with [provenance](https://docs.npmjs.com/generating-provenance-statements), and standalone binaries are published with SHA-256 checksums.
|
|
49
|
+
|
|
26
50
|
## Install
|
|
27
51
|
|
|
28
52
|
Every install method ships the same CLI (`agentsmesh`, plus the shorter `amsh` alias) and the same TypeScript library.
|
|
@@ -45,11 +69,14 @@ Standalone binaries are also on [GitHub Releases](https://github.com/sampleXbro/
|
|
|
45
69
|
|
|
46
70
|
## 60-second quickstart
|
|
47
71
|
|
|
48
|
-
Works on Linux, macOS, and Windows. After [installing](#install):
|
|
72
|
+
Works on Linux, macOS, and Windows. After [installing](#install), `agentsmesh init` adapts to your repo:
|
|
73
|
+
|
|
74
|
+
- **Already using AI tools?** It detects your existing `.cursor/`, `.claude/`, `.github/copilot-instructions.md`, and more, and offers to import them all into one `.agentsmesh/` source — nothing rewritten by hand. (`agentsmesh init --yes` does it non-interactively.)
|
|
75
|
+
- **Starting fresh?** It scaffolds a minimal `.agentsmesh/` to grow from.
|
|
49
76
|
|
|
50
77
|
```bash
|
|
51
|
-
agentsmesh init #
|
|
52
|
-
agentsmesh generate # write native
|
|
78
|
+
agentsmesh init # detect & import existing configs, or scaffold fresh
|
|
79
|
+
agentsmesh generate # write each tool's native config from the one source
|
|
53
80
|
agentsmesh check # CI-friendly drift gate against .agentsmesh/.lock
|
|
54
81
|
```
|
|
55
82
|
|
|
@@ -99,20 +126,44 @@ AGENTS.md
|
|
|
99
126
|
|
|
100
127
|
Edit canonical sources, run `agentsmesh generate`, and every native file above is (re)written for you — always in sync. Alongside the directory, `agentsmesh.yaml` selects which targets and features are enabled, `agentsmesh.local.yaml` holds per-developer overrides (gitignored), and `.agentsmesh/.lock` records the checksums that `agentsmesh check` enforces.
|
|
101
128
|
|
|
129
|
+
<div align="center">
|
|
130
|
+
<img src="https://raw.githubusercontent.com/sampleXbro/agentsmesh/master/assets/generate-demo.gif" alt="agentsmesh detects existing tool configs, imports them into one source, and generates native config for every tool" width="100%" />
|
|
131
|
+
</div>
|
|
132
|
+
|
|
102
133
|
## Teach your agents: lessons
|
|
103
134
|
|
|
104
|
-
Lessons give your AI agents a **memory of past mistakes** — read *before* they touch anything, written *after* something goes wrong, so the same mistake doesn't happen twice in any tool.
|
|
135
|
+
This is the part no other config-sync tool has. Lessons give your AI agents a **memory of past mistakes** — read *before* they touch anything, written *after* something goes wrong, so the same mistake doesn't happen twice in any tool. It's what turns a static pile of rules into an agent that gets better at *your* codebase over time.
|
|
136
|
+
|
|
137
|
+
<div align="center">
|
|
138
|
+
<img src="https://raw.githubusercontent.com/sampleXbro/agentsmesh/master/assets/lessons-demo.gif" alt="an AI agent captures a lesson after a failure, then recalls it before editing the same file — triggered by file, command, or keyword" width="100%" />
|
|
139
|
+
</div>
|
|
105
140
|
|
|
106
141
|
The memory is one git-tracked file, `.agentsmesh/lessons/lessons.json`, and every agent talks to it through two commands:
|
|
107
142
|
|
|
108
143
|
- **Recall** — before an edit or a state-changing command, the agent runs `agentsmesh lessons query --file <path> --cmd <command>` and follows the rules that match.
|
|
109
144
|
- **Capture** — right after a failure (red test, lint error, review comment, wrong assumption), it saves the rule with `agentsmesh lessons add "<rule>" --topic <id> --trigger-file <glob>`.
|
|
110
145
|
|
|
146
|
+
Rules can be **scoped** (fire only on a matching file, command, or keyword) or **always-on** (`--scope always`) for universal standards that apply to every task — delivered on each task automatically, no trigger needed.
|
|
147
|
+
|
|
148
|
+
Opt in with `AGENTSMESH_LESSONS_TELEMETRY=1` and agentsmesh goes a step further — it tracks whether a recalled lesson actually **prevented** the repeat, quietly down-ranks rules that never help, and flags them in `agentsmesh lessons validate`. Off by default and per-machine; the shared graph is your rules, the effectiveness is your own history.
|
|
149
|
+
|
|
150
|
+
In practice:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# An agent breaks the Windows build, finds the cause, and writes the lesson down:
|
|
154
|
+
agentsmesh lessons add "Normalize CLI display paths to forward slashes" \
|
|
155
|
+
--topic windows-paths --trigger-file "src/cli/**/*.ts"
|
|
156
|
+
|
|
157
|
+
# Days later, any agent — in any tool — about to touch that path recalls it first:
|
|
158
|
+
agentsmesh lessons query --file src/cli/output.ts
|
|
159
|
+
# → "Normalize CLI display paths to forward slashes"
|
|
160
|
+
```
|
|
161
|
+
|
|
111
162
|
```bash
|
|
112
163
|
agentsmesh init --lessons && agentsmesh generate # wire the recall/capture loop once
|
|
113
164
|
```
|
|
114
165
|
|
|
115
|
-
`init --lessons` drops a small always-on rule into `.agentsmesh/rules/_root.md` (so every target gets the habit), seeds the full operating manual as a `lessons` skill where supported, and wires a recall hook
|
|
166
|
+
`init --lessons` drops a small always-on rule into `.agentsmesh/rules/_root.md` (so every target gets the habit), seeds the full operating manual as a `lessons` skill where supported, and wires a recall hook on hook-capable tools — a `PreToolUse` first-touch guard plus a `PostToolUse` fallback for file/command scope, a `UserPromptSubmit` pass so conceptual (`keyword`) and always-on lessons recall against the **task text**, a `PostToolUseFailure` advisory nudge to capture at the moment something breaks, and a `SessionStart` reset so recall re-surfaces lessons a long chat has summarized away. Agents without shell access use the matching MCP tools (`lessons_query` / `lessons_add`). Because the graph is a normal git-tracked file, a lesson one agent learns today helps every teammate's agent tomorrow, and every change is reviewable like any other diff.
|
|
116
167
|
|
|
117
168
|
Full walkthrough: [Teach your AI agents with lessons](https://samplexbro.github.io/agentsmesh/guides/lessons/) · [`agentsmesh lessons` reference](https://samplexbro.github.io/agentsmesh/cli/lessons/).
|
|
118
169
|
|
|
@@ -125,8 +176,8 @@ Full walkthrough: [Teach your AI agents with lessons](https://samplexbro.github.
|
|
|
125
176
|
- **Migrate between tools** — `convert --from <a> --to <b>` rewrites one tool's config directly into another's native format. [convert →](https://samplexbro.github.io/agentsmesh/cli/convert/)
|
|
126
177
|
- **Global mode** — `~/.agentsmesh/` syncs your personal config to `~/.claude/`, `~/.cursor/`, `~/.codex/`, and more. Every command accepts `--global`. [Global paths →](https://samplexbro.github.io/agentsmesh/reference/supported-tools/#global-mode)
|
|
127
178
|
- **Team-safe and CI-ready** — `check` is a drift gate against `.agentsmesh/.lock`, `diff` previews changes, `merge` rebuilds the lock after a 3-way Git conflict, and `lock_features` + per-feature `strategy` prevent accidental overrides. `lint` adds cross-target warnings (`silent-drop-guard`, `hook-script-references`, `rule-scope-inversion`) for content a tool would silently mishandle. [check →](https://samplexbro.github.io/agentsmesh/cli/check/) · [lint →](https://samplexbro.github.io/agentsmesh/cli/lint/)
|
|
128
|
-
- **Community packs and `extends`** — install shared rules, skills, agents, and commands from any git repo (`install`, `--sync`, `refresh`, remote `extends`); a multi-signal classifier auto-detects Anthropic-style skill packs. Elevated artifacts (hooks, permissions, MCP) from remote sources are stripped unless you opt in with `--accept
|
|
129
|
-
- **Plugins** — ship support for a new tool as a standalone npm package, with full parity to built-in targets (project + global, conversions, lint hooks, hook post-processing). [Build a plugin →](https://samplexbro.github.io/agentsmesh/guides/building-plugins/)
|
|
179
|
+
- **Community packs and `extends`** — install shared rules, skills, agents, and commands from any git repo (`install`, `--sync`, `refresh`, remote `extends`); a multi-signal classifier auto-detects Anthropic-style skill packs. Elevated artifacts (hooks, permissions, MCP) from remote sources are stripped unless you opt in — with `--accept-*` on `install`, or `accept:` on a remote `extends` entry. [Install reference →](https://samplexbro.github.io/agentsmesh/cli/install/)
|
|
180
|
+
- **Plugins — add a tool without waiting for a release** — ship support for a new AI tool as a standalone npm package, with full parity to built-in targets (project + global, conversions, lint hooks, hook post-processing). When a tool ships or changes its format, you don't file an issue and wait on the maintainer — you publish a plugin. [Build a plugin →](https://samplexbro.github.io/agentsmesh/guides/building-plugins/)
|
|
130
181
|
- **Schema-validated configs** — each config ships a JSON Schema, so editors give you autocomplete and validation out of the box. [JSON schemas →](https://samplexbro.github.io/agentsmesh/reference/json-schemas/)
|
|
131
182
|
- **Typed programmatic API** — drive `generate` / `import` / `lint` / `diff` / `check` from scripts or CI via `agentsmesh`, `/engine`, `/canonical`, `/targets`, `/lessons`. [API reference →](https://samplexbro.github.io/agentsmesh/reference/programmatic-api/)
|
|
132
183
|
- **Self-serve MCP server** — `agentsmesh mcp` (seeded by `init`) exposes canonical config as MCP tools so agents can introspect rules, commands, and skills and trigger `generate` in-conversation. [MCP server →](https://samplexbro.github.io/agentsmesh/reference/mcp-server/)
|
|
@@ -135,9 +186,11 @@ Full walkthrough: [Teach your AI agents with lessons](https://samplexbro.github.
|
|
|
135
186
|
> [!TIP]
|
|
136
187
|
> Commit **both** `.agentsmesh/` and the generated tool files, the same way you commit `package-lock.json`: they're deterministic build output that the AI tools read directly, and `agentsmesh check` guards the two from drifting.
|
|
137
188
|
|
|
138
|
-
## Why not just `AGENTS.md`?
|
|
189
|
+
## Why not Ruler, rulesync, or just `AGENTS.md`?
|
|
190
|
+
|
|
191
|
+
**vs. `AGENTS.md`** — [`AGENTS.md`](https://agents.md) is a great shared instruction file, and AgentsMesh emits it natively wherever a tool supports it. But a single markdown file isn't enough on its own: most assistants expose configuration *beyond* it — Cursor's `.cursor/rules/*.mdc` and MCP config, Claude Code's agents/skills/commands/hooks/permissions, Copilot's `.github/instructions/`, Gemini's `.gemini/settings.json`, and so on — and those surfaces don't overlap. AgentsMesh canonicalizes all of them so you never have to pick one tool's surface as the lowest common denominator.
|
|
139
192
|
|
|
140
|
-
[
|
|
193
|
+
**vs. other sync tools** — [Ruler](https://github.com/intellectronica/ruler) and [rulesync](https://github.com/dyoshikawa/rulesync) solve the rules-distribution half well. AgentsMesh goes further on the parts that are hardest to keep in sync: a shared [lessons](#teach-your-agents-lessons) memory your agents learn from, lossless two-way [import](https://samplexbro.github.io/agentsmesh/cli/import/), automatic cross-tool [link rebasing](https://samplexbro.github.io/agentsmesh/reference/generation-pipeline/), [plugins](https://samplexbro.github.io/agentsmesh/guides/building-plugins/) so a new tool ships without a release, and [lint](https://samplexbro.github.io/agentsmesh/cli/lint/) that warns before a tool would silently drop content. See the [full comparison](#how-agentsmesh-compares) and the [alternatives guide](https://samplexbro.github.io/agentsmesh/reference/alternatives/).
|
|
141
194
|
|
|
142
195
|
## Commands
|
|
143
196
|
|
package/dist/canonical.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as CanonicalFiles, V as ValidatedConfig } from './schema-
|
|
2
|
-
export { C as CanonicalAgent, a as CanonicalCommand, c as CanonicalRule, d as CanonicalSkill, H as HookEntry, e as Hooks, I as IgnorePatterns, M as McpConfig, f as McpServer, P as Permissions, S as SkillSupportingFile, g as StdioMcpServer, U as UrlMcpServer } from './schema-
|
|
1
|
+
import { b as CanonicalFiles, V as ValidatedConfig } from './schema-CH_JJep8.js';
|
|
2
|
+
export { C as CanonicalAgent, a as CanonicalCommand, c as CanonicalRule, d as CanonicalSkill, H as HookEntry, e as Hooks, I as IgnorePatterns, M as McpConfig, f as McpServer, P as Permissions, S as SkillSupportingFile, g as StdioMcpServer, U as UrlMcpServer } from './schema-CH_JJep8.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
interface UnrecognizedFormatsWarningOptions {
|
package/dist/canonical.js
CHANGED
|
@@ -2874,6 +2874,18 @@ var init_linter = __esm({
|
|
|
2874
2874
|
}
|
|
2875
2875
|
});
|
|
2876
2876
|
|
|
2877
|
+
// src/core/hook-types.ts
|
|
2878
|
+
var BEST_EFFORT_HOOK_EVENTS;
|
|
2879
|
+
var init_hook_types = __esm({
|
|
2880
|
+
"src/core/hook-types.ts"() {
|
|
2881
|
+
BEST_EFFORT_HOOK_EVENTS = /* @__PURE__ */ new Set([
|
|
2882
|
+
"UserPromptSubmit",
|
|
2883
|
+
"PostToolUseFailure",
|
|
2884
|
+
"SessionStart"
|
|
2885
|
+
]);
|
|
2886
|
+
}
|
|
2887
|
+
});
|
|
2888
|
+
|
|
2877
2889
|
// src/core/lint/shared/helpers.ts
|
|
2878
2890
|
function createWarning(file, target31, message) {
|
|
2879
2891
|
return {
|
|
@@ -2889,6 +2901,13 @@ function formatOxfordComma(items) {
|
|
|
2889
2901
|
if (items.length === 2) return `${items[0]} and ${items[1]}`;
|
|
2890
2902
|
return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
|
|
2891
2903
|
}
|
|
2904
|
+
function unsupportedHookEventNames(hooks, supportedEvents) {
|
|
2905
|
+
if (!hooks) return [];
|
|
2906
|
+
const supported = new Set(supportedEvents);
|
|
2907
|
+
return Object.keys(hooks).filter(
|
|
2908
|
+
(event) => !supported.has(event) && !BEST_EFFORT_HOOK_EVENTS.has(event)
|
|
2909
|
+
);
|
|
2910
|
+
}
|
|
2892
2911
|
function createUnsupportedHookWarning(event, target31, supportedEvents, options) {
|
|
2893
2912
|
const by = options?.unsupportedBy ?? target31;
|
|
2894
2913
|
const supported = formatOxfordComma(supportedEvents);
|
|
@@ -2900,6 +2919,7 @@ function createUnsupportedHookWarning(event, target31, supportedEvents, options)
|
|
|
2900
2919
|
}
|
|
2901
2920
|
var init_helpers = __esm({
|
|
2902
2921
|
"src/core/lint/shared/helpers.ts"() {
|
|
2922
|
+
init_hook_types();
|
|
2903
2923
|
}
|
|
2904
2924
|
});
|
|
2905
2925
|
|
|
@@ -6217,8 +6237,7 @@ var init_linter5 = __esm({
|
|
|
6217
6237
|
// src/targets/augment-code/lint.ts
|
|
6218
6238
|
function lintHooks3(canonical) {
|
|
6219
6239
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
6220
|
-
|
|
6221
|
-
return Object.keys(canonical.hooks).filter((event) => !supportedSet.has(event)).map(
|
|
6240
|
+
return unsupportedHookEventNames(canonical.hooks, SUPPORTED_HOOK_EVENTS).map(
|
|
6222
6241
|
(event) => createUnsupportedHookWarning(event, "augment-code", SUPPORTED_HOOK_EVENTS, {
|
|
6223
6242
|
unsupportedBy: "AugmentCode hooks"
|
|
6224
6243
|
})
|
|
@@ -10223,8 +10242,7 @@ function lintCommands3(canonical) {
|
|
|
10223
10242
|
function lintHooks5(canonical) {
|
|
10224
10243
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
10225
10244
|
const supported = ["PreToolUse", "PostToolUse", "Notification", "UserPromptSubmit"];
|
|
10226
|
-
const
|
|
10227
|
-
const diagnostics = Object.keys(canonical.hooks).filter((event) => !supportedSet.has(event)).map(
|
|
10245
|
+
const diagnostics = unsupportedHookEventNames(canonical.hooks, supported).map(
|
|
10228
10246
|
(event) => createUnsupportedHookWarning(event, "copilot", supported, {
|
|
10229
10247
|
unsupportedBy: "Copilot hooks"
|
|
10230
10248
|
})
|
|
@@ -11341,7 +11359,7 @@ var init_permissions2 = __esm({
|
|
|
11341
11359
|
// src/targets/cursor/hook-format.ts
|
|
11342
11360
|
function unmappedCursorHookEvents(hooks) {
|
|
11343
11361
|
return Object.keys(hooks).filter(
|
|
11344
|
-
(event) => Array.isArray(hooks[event]) && hooks[event].length > 0 && !(event in CANONICAL_TO_CURSOR)
|
|
11362
|
+
(event) => Array.isArray(hooks[event]) && hooks[event].length > 0 && !(event in CANONICAL_TO_CURSOR) && !BEST_EFFORT_HOOK_EVENTS.has(event)
|
|
11345
11363
|
);
|
|
11346
11364
|
}
|
|
11347
11365
|
function toCursorHooks(hooks) {
|
|
@@ -11389,6 +11407,7 @@ function cursorHooksToCanonical(hooks) {
|
|
|
11389
11407
|
var CANONICAL_TO_CURSOR, CURSOR_TO_CANONICAL;
|
|
11390
11408
|
var init_hook_format = __esm({
|
|
11391
11409
|
"src/targets/cursor/hook-format.ts"() {
|
|
11410
|
+
init_hook_types();
|
|
11392
11411
|
init_hook_command();
|
|
11393
11412
|
CANONICAL_TO_CURSOR = {
|
|
11394
11413
|
PreToolUse: "preToolUse",
|
|
@@ -13839,8 +13858,9 @@ function lintCommands6(canonical) {
|
|
|
13839
13858
|
function lintHooks7(canonical) {
|
|
13840
13859
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
13841
13860
|
const supported = ["PreToolUse", "PostToolUse", "Notification"];
|
|
13842
|
-
|
|
13843
|
-
|
|
13861
|
+
return unsupportedHookEventNames(canonical.hooks, supported).map(
|
|
13862
|
+
(event) => createUnsupportedHookWarning(event, "gemini-cli", supported)
|
|
13863
|
+
);
|
|
13844
13864
|
}
|
|
13845
13865
|
var init_lint14 = __esm({
|
|
13846
13866
|
"src/targets/gemini-cli/lint.ts"() {
|
|
@@ -16092,8 +16112,7 @@ var init_linter20 = __esm({
|
|
|
16092
16112
|
function lintHooks10(canonical) {
|
|
16093
16113
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
16094
16114
|
const supported = ["PreToolUse", "PostToolUse", "UserPromptSubmit", "SubagentStop"];
|
|
16095
|
-
|
|
16096
|
-
return Object.keys(canonical.hooks).filter((event) => !supportedSet.has(event)).map(
|
|
16115
|
+
return unsupportedHookEventNames(canonical.hooks, supported).map(
|
|
16097
16116
|
(event) => createUnsupportedHookWarning(event, "kiro", supported, { unsupportedBy: "Kiro hooks" })
|
|
16098
16117
|
);
|
|
16099
16118
|
}
|
|
@@ -20874,7 +20893,9 @@ async function resolveExtendPaths(config, configDir, options = {}) {
|
|
|
20874
20893
|
as: ext.as,
|
|
20875
20894
|
version: fetched.version,
|
|
20876
20895
|
path: ext.path,
|
|
20877
|
-
pick: ext.pick
|
|
20896
|
+
pick: ext.pick,
|
|
20897
|
+
isRemote: true,
|
|
20898
|
+
accept: ext.accept
|
|
20878
20899
|
});
|
|
20879
20900
|
continue;
|
|
20880
20901
|
}
|
|
@@ -20891,7 +20912,9 @@ async function resolveExtendPaths(config, configDir, options = {}) {
|
|
|
20891
20912
|
target: ext.target,
|
|
20892
20913
|
as: ext.as,
|
|
20893
20914
|
path: ext.path,
|
|
20894
|
-
pick: ext.pick
|
|
20915
|
+
pick: ext.pick,
|
|
20916
|
+
isRemote: false,
|
|
20917
|
+
accept: ext.accept
|
|
20895
20918
|
});
|
|
20896
20919
|
}
|
|
20897
20920
|
return result;
|
|
@@ -22421,6 +22444,47 @@ function applyExtendPick(canonical, features, pick, extendName) {
|
|
|
22421
22444
|
return next;
|
|
22422
22445
|
}
|
|
22423
22446
|
|
|
22447
|
+
// src/install/core/elevated-artifacts.ts
|
|
22448
|
+
function stripUntrustedElevatedArtifacts(canonical, options) {
|
|
22449
|
+
if (options.sourceKind === "local") {
|
|
22450
|
+
return { canonical, stripped: [] };
|
|
22451
|
+
}
|
|
22452
|
+
const stripped = [];
|
|
22453
|
+
let hooks = canonical.hooks;
|
|
22454
|
+
let permissions = canonical.permissions;
|
|
22455
|
+
let mcp = canonical.mcp;
|
|
22456
|
+
if (hooks !== null && !options.acceptHooks) {
|
|
22457
|
+
hooks = null;
|
|
22458
|
+
stripped.push("hooks");
|
|
22459
|
+
}
|
|
22460
|
+
if (permissions !== null && !options.acceptPermissions) {
|
|
22461
|
+
permissions = null;
|
|
22462
|
+
stripped.push("permissions");
|
|
22463
|
+
}
|
|
22464
|
+
if (mcp !== null && !options.acceptMcp) {
|
|
22465
|
+
mcp = null;
|
|
22466
|
+
stripped.push("mcp");
|
|
22467
|
+
}
|
|
22468
|
+
if (stripped.length === 0) {
|
|
22469
|
+
return { canonical, stripped: [] };
|
|
22470
|
+
}
|
|
22471
|
+
return {
|
|
22472
|
+
canonical: { ...canonical, hooks, permissions, mcp },
|
|
22473
|
+
stripped
|
|
22474
|
+
};
|
|
22475
|
+
}
|
|
22476
|
+
|
|
22477
|
+
// src/canonical/extends/extend-elevated.ts
|
|
22478
|
+
function gateExtendElevatedArtifacts(canonical, ext) {
|
|
22479
|
+
const accept = ext.accept ?? [];
|
|
22480
|
+
return stripUntrustedElevatedArtifacts(canonical, {
|
|
22481
|
+
sourceKind: ext.isRemote ? "git" : "local",
|
|
22482
|
+
acceptHooks: accept.includes("hooks"),
|
|
22483
|
+
acceptPermissions: accept.includes("permissions"),
|
|
22484
|
+
acceptMcp: accept.includes("mcp")
|
|
22485
|
+
});
|
|
22486
|
+
}
|
|
22487
|
+
|
|
22424
22488
|
// src/install/pack/pack-reader.ts
|
|
22425
22489
|
init_fs();
|
|
22426
22490
|
|
|
@@ -22454,7 +22518,14 @@ var extendSourceSchema = z.object({
|
|
|
22454
22518
|
features: z.array(featureSchema),
|
|
22455
22519
|
/** Repo-relative POSIX path for discovery (skill packs, nested .agentsmesh). */
|
|
22456
22520
|
path: z.string().optional(),
|
|
22457
|
-
pick: extendPickSchema.optional()
|
|
22521
|
+
pick: extendPickSchema.optional(),
|
|
22522
|
+
/**
|
|
22523
|
+
* Per-entry consent for "elevated" artifacts (`hooks`, `permissions`, `mcp`)
|
|
22524
|
+
* from a remote source. These control local code execution at generate time,
|
|
22525
|
+
* so for non-local extends they are stripped by default and only merged for
|
|
22526
|
+
* the artifacts listed here. Local extends are trusted and ignore this field.
|
|
22527
|
+
*/
|
|
22528
|
+
accept: z.array(z.enum(["hooks", "permissions", "mcp"])).optional()
|
|
22458
22529
|
});
|
|
22459
22530
|
var collaborationSchema = z.object({
|
|
22460
22531
|
strategy: z.enum(["merge", "lock", "last-wins"]).default("merge"),
|
|
@@ -22646,7 +22717,14 @@ async function loadCanonicalWithExtends(config, configDir, options = {}, canonic
|
|
|
22646
22717
|
for (const ext of resolvedExtends) {
|
|
22647
22718
|
const extCanonical = await loadCanonicalForExtend(ext);
|
|
22648
22719
|
const filtered = filterCanonicalByFeatures(extCanonical, ext.features);
|
|
22649
|
-
const
|
|
22720
|
+
const gated = gateExtendElevatedArtifacts(filtered, ext);
|
|
22721
|
+
if (gated.stripped.length > 0) {
|
|
22722
|
+
const list = gated.stripped.join(", ");
|
|
22723
|
+
logger.warn(
|
|
22724
|
+
`[agentsmesh] Extend "${ext.name}": stripped elevated artifacts from a remote source: ${list}. Add \`accept: [${list}]\` to this extends entry in agentsmesh.yaml to keep them.`
|
|
22725
|
+
);
|
|
22726
|
+
}
|
|
22727
|
+
const picked = applyExtendPick(gated.canonical, ext.features, ext.pick, ext.name);
|
|
22650
22728
|
merged = mergeCanonicalFiles(merged, picked);
|
|
22651
22729
|
}
|
|
22652
22730
|
const packsCanonical = await loadPacksCanonical(canonicalDir);
|