agentsmesh 0.29.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 +26 -0
- package/README.md +5 -1
- package/dist/canonical.js +28 -9
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +223 -199
- package/dist/engine.js +38 -12
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +158 -42
- 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/targets.js +28 -9
- package/dist/targets.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
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
|
+
|
|
3
29
|
## 0.29.0
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -143,6 +143,10 @@ The memory is one git-tracked file, `.agentsmesh/lessons/lessons.json`, and ever
|
|
|
143
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.
|
|
144
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>`.
|
|
145
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
|
+
|
|
146
150
|
In practice:
|
|
147
151
|
|
|
148
152
|
```bash
|
|
@@ -159,7 +163,7 @@ agentsmesh lessons query --file src/cli/output.ts
|
|
|
159
163
|
agentsmesh init --lessons && agentsmesh generate # wire the recall/capture loop once
|
|
160
164
|
```
|
|
161
165
|
|
|
162
|
-
`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.
|
|
163
167
|
|
|
164
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/).
|
|
165
169
|
|
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
|
}
|