Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
26eb640
chore(lessons): capture the awesome-list submission validation rule
serhiizhabskiy Sep 22, 2026
6a143c7
chore(lessons): capture the staged-validator rule
serhiizhabskiy Sep 22, 2026
53f0411
feat(plugin): make one bundle install in Codex as well as Claude Code
serhiizhabskiy Sep 22, 2026
6772a6a
chore(lessons): capture the plugin bundle contract and the containmen…
serhiizhabskiy Sep 22, 2026
4043bfd
fix(plugin): drop an authentication value Codex rejects
serhiizhabskiy Sep 22, 2026
2684c0c
chore(lessons): capture the Codex marketplace policy rule
serhiizhabskiy Sep 22, 2026
436730d
chore(lessons): capture the post-merge version sync rule
serhiizhabskiy Sep 22, 2026
e01e495
chore(lessons): capture plugin-load verification, written via the plu…
serhiizhabskiy Sep 22, 2026
3f24166
chore(lessons): capture the plugin standing-instruction gap
serhiizhabskiy Sep 22, 2026
2cb8b48
feat(mcp): hand the lessons contract to every client at initialize
serhiizhabskiy Sep 22, 2026
d374116
chore(lessons): correct the MCP instructions signature and supersede
serhiizhabskiy Sep 22, 2026
f502c98
chore(lessons): capture the audit duplication-claim rule
serhiizhabskiy Sep 22, 2026
b7ab200
refactor: cut dead code and collapse three duplicated generators
serhiizhabskiy Sep 22, 2026
a7861bd
chore(lessons): capture the regex block-deletion trap
serhiizhabskiy Sep 22, 2026
fa339b1
Merge remote-tracking branch 'refs/remotes/checked/master2' into develop
serhiizhabskiy Sep 22, 2026
fcc2513
chore(release): sync plugin manifest versions to 0.40.0
serhiizhabskiy Sep 22, 2026
5f9e443
fix(mcp): stop handing a lessons mandate to projects without lessons
serhiizhabskiy Sep 22, 2026
7589475
chore(lessons): capture the state-aware standing-text rule
serhiizhabskiy Sep 22, 2026
cea0c7e
feat(lessons): make lessons team-safe, reach more hosts, and resist h…
serhiizhabskiy Sep 23, 2026
7f0f88e
chore(lessons): capture the lessons-hardening rules
serhiizhabskiy Sep 23, 2026
fcdf9a3
refactor(lessons): share the graph path, empty graph and file-read he…
serhiizhabskiy Sep 23, 2026
4777ddc
refactor(lessons): cut needless complexity from the lessons hardening
serhiizhabskiy Sep 23, 2026
a21fda2
chore(lessons): capture the cleanup rules and retire lessons naming r…
serhiizhabskiy Sep 23, 2026
3dcf573
chore(lessons): capture the QA subagent working-directory rule
serhiizhabskiy Sep 23, 2026
3bbf68b
fix(lessons): close the high and medium defects from manual QA
serhiizhabskiy Sep 23, 2026
d14c61a
chore(lessons): capture the QA-fix rules and supersede outdated ones
serhiizhabskiy Sep 23, 2026
e2f4219
fix(install): update a re-installed local pack in place and stop sile…
serhiizhabskiy Sep 23, 2026
1d0fdaf
chore(lessons): capture the pack re-install, macOS case and git add r…
serhiizhabskiy Sep 23, 2026
ab63a79
fix(generate): leave the lock untouched when nothing changed
serhiizhabskiy Sep 23, 2026
6b8bf1e
chore(lessons): capture the lock-content rule and retire the wrong e2…
serhiizhabskiy Sep 23, 2026
499f7c7
fix(lessons): refuse bad CLI input clearly instead of acting on it
serhiizhabskiy Sep 23, 2026
450791d
chore(lessons): capture the trigger-path, flag-value and rule-length …
serhiizhabskiy Sep 23, 2026
3d7f809
test(typecheck): fix hidden fixture type errors and add typecheck:tests
serhiizhabskiy Sep 23, 2026
95d82ff
chore(lessons): capture the typecheck:tests, fixture-cast and exclude…
serhiizhabskiy Sep 23, 2026
05fc2e7
ci: type-check the tests on one quality matrix entry
serhiizhabskiy Sep 23, 2026
b2bfc56
fix(lessons): close hook, merge driver and log edge cases from manual QA
serhiizhabskiy Sep 23, 2026
1e3f237
chore(lessons): capture the vitest transform, jsonl trim and Copilot …
serhiizhabskiy Sep 23, 2026
174b3cd
refactor(install): split install selection out of run-install-execute
serhiizhabskiy Sep 23, 2026
c5305a8
chore(lessons): capture the copied-build version rule
serhiizhabskiy Sep 23, 2026
55e5545
docs(merge): say that merge keeps the lock outputs map
serhiizhabskiy Sep 23, 2026
ec2ad58
chore(lessons): capture the merge docs sync rule
serhiizhabskiy Sep 23, 2026
579a6c5
fix(check): give the fix that matches the drift kind
serhiizhabskiy Sep 23, 2026
f083528
chore(lessons): capture the conflicted-lock check rule
serhiizhabskiy Sep 23, 2026
cc5cc29
feat(mcp): report lockConflict in the check tool result
serhiizhabskiy Sep 23, 2026
c6a6f38
feat(check): add lockConflict to the public LockSyncReport
serhiizhabskiy Sep 23, 2026
591d9f2
chore(lessons): capture the public-field consumer smoke rule
serhiizhabskiy Sep 23, 2026
30e1edb
refactor(check): drop the duplicate no-lock result and the one-caller…
serhiizhabskiy Sep 23, 2026
975d1ea
chore(lessons): capture the release silent-break audit rule
serhiizhabskiy Sep 23, 2026
7857ff1
fix(mcp): make check and generate report what the CLI does
serhiizhabskiy Sep 23, 2026
9794e8e
chore(lessons): capture the vi.fn mock typing rule
serhiizhabskiy Sep 23, 2026
98cb625
docs(release): add upgrade notes for the next release
serhiizhabskiy Sep 23, 2026
bb1d46b
test(lessons): make the git merge and Windows tests pass on CI runners
serhiizhabskiy Sep 23, 2026
cab70b6
fix(lock): retry a Windows EPERM while evicting a stale lock owner
serhiizhabskiy Sep 23, 2026
837a9d9
chore(lessons): capture the CI identity, Windows test and lock race r…
serhiizhabskiy Sep 23, 2026
117795e
test(lock): cover lock error paths, the ps identity and a busy seen-s…
serhiizhabskiy Sep 23, 2026
2abb9a9
fix(lock): retry short Windows EPERM when claiming a lock and in the …
serhiizhabskiy Sep 24, 2026
fa7400e
chore(lessons): capture the shared Windows retry and long-sleep rules
serhiizhabskiy Sep 24, 2026
2c18bea
fix(lock): wait out short Windows errors while claiming or reading a …
serhiizhabskiy Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .agents/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
]
},
{
"matcher": "Edit|Write|Bash",
"matcher": "Edit|Write|NotebookEdit|Bash|PowerShell",
"hooks": [
{
"type": "command",
Expand Down
2 changes: 1 addition & 1 deletion .agents/plugins/agentsmesh/hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
]
},
{
"matcher": "Edit|Write|Bash",
"matcher": "Edit|Write|NotebookEdit|Bash|PowerShell",
"hooks": [
{
"type": "command",
Expand Down
19 changes: 19 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "agentsmesh",
"interface": {
"displayName": "AgentsMesh"
},
"plugins": [
{
"name": "agentsmesh-lessons",
"source": {
"source": "local",
"path": "./plugins/agentsmesh-lessons"
},
"policy": {
"installation": "AVAILABLE"
},
"category": "Productivity"
}
]
}
3 changes: 2 additions & 1 deletion .agents/skills/lessons/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ At least one _effective_ trigger is required (or `--scope always` for a universa
the capture is rejected (`UNRECALLABLE_LESSON`); prefer `--trigger-file`. No shell → MCP `lessons_query`,
`lessons_add`, `lessons_topics`, `lessons_show`, `lessons_deprecate`. Run
`agentsmesh lessons --help` for every subcommand and flag: query, add, topics, show,
deprecate, merge, untrigger, strip-markers, prune, journal, validate, stats, import-md.
deprecate, merge, untrigger, strip-markers, prune, journal, validate, resolve, stats, import-md.
A git merge conflict in `lessons.json` → run `agentsmesh lessons resolve`; never hand-edit it.

### Rationalization Prevention — these excuses mean STOP

Expand Down
108 changes: 53 additions & 55 deletions .agentsmesh/.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .agentsmesh/hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PreToolUse:
- matcher: Bash
type: command
command: "echo \"Running: $(jq -r '.tool_input.command' < /dev/stdin)\""
- matcher: Edit|Write|Bash
- matcher: Edit|Write|NotebookEdit|Bash|PowerShell
type: command
command: agentsmesh lessons hook
PostToolUse:
Expand Down
1,805 changes: 1,748 additions & 57 deletions .agentsmesh/lessons/lessons.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion .agentsmesh/skills/lessons/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ At least one _effective_ trigger is required (or `--scope always` for a universa
the capture is rejected (`UNRECALLABLE_LESSON`); prefer `--trigger-file`. No shell → MCP `lessons_query`,
`lessons_add`, `lessons_topics`, `lessons_show`, `lessons_deprecate`. Run
`agentsmesh lessons --help` for every subcommand and flag: query, add, topics, show,
deprecate, merge, untrigger, strip-markers, prune, journal, validate, stats, import-md.
deprecate, merge, untrigger, strip-markers, prune, journal, validate, resolve, stats, import-md.
A git merge conflict in `lessons.json` → run `agentsmesh lessons resolve`; never hand-edit it.

### Rationalization Prevention — these excuses mean STOP

Expand Down
15 changes: 15 additions & 0 deletions .changeset/calm-lessons-guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'agentsmesh': minor
---

Lessons are harder to lose and easier to use correctly, after a full manual QA pass.

Team merges: if git could not start the lessons merge driver, it kept only your side of `lessons.json` with no conflict markers, and every check still passed. Now `lessons validate`, `check` and `generate --check` fail while the file is missing the other branch's lessons, and tell you to run `agentsmesh lessons resolve` before `git add`. The driver is also only saved when git can start it later (npx caches and package-script bin folders on PATH no longer count, and the npx form needs agentsmesh at the repository root or installed globally). `lessons resolve` now works again after you fix a broken side by hand in the file.

The recall hook never breaks your tool: a log file it cannot write, or a bad line in a log, no longer makes it fail or lose a lesson for the session. A failed read (for example reading a file that does not exist yet) is no longer counted against a later write. A multi-file patch shows each warned rule once and stays under the size cap. Invisible and look-alike characters can no longer fake the end of the recalled-lessons block. An unreadable graph is now also reported when a session starts with no prompt. The hook does nothing in a folder with no lessons project, such as your home folder.

The `lessons` CLI works from any subfolder of a project, like git. It refuses an unquoted multi-word rule (instead of saving only its first word) and a single-value flag given twice. Re-adding a lesson says what changed. A regex the linear engine cannot run is dropped with a `DEAD_COMMAND_PATTERN` warning when the lesson has another trigger, or refused as `UNRECALLABLE_LESSON` (exit 2) when it is the only one. Every lessons command, and every MCP lessons tool, now explains an unreadable graph (merge conflict, bad JSON, `SCHEMA_INVALID`, newer version) instead of printing parser output. A negated glob (`!path`) is flagged as broad. A lessons write that lost its lock (the process was paused past the 60 s stale window) refuses to save instead of erasing a later write, and a lock dated in the future no longer blocks writers.

MCP lessons tools never create a lessons graph in your home folder or outside a project: they use the nearest lessons folder, then `agentsmesh.yaml`, then the git repository root, and otherwise refuse writes with `NO_PROJECT`. `lessons_show` accepts a lesson id, `lessons_query` with `always` honors `session` and `no_dedup`, and refused writes return `VALIDATION_FAILED` with the finding codes.

Installed pack hooks are no longer lost: two packs on the same event are combined, a pack adds to an extend's hooks for that event, and a local `hooks.yaml` event keeps the pack's hooks after its own. Before, `agentsmesh init --lessons` (which adds the recall hook locally) silently removed installed pack hooks for the same event. Extends layers still override per event, as documented. To drop a pack hook, uninstall the pack or leave `hooks` out of its features.
5 changes: 5 additions & 0 deletions .changeset/check-drift-hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'agentsmesh': patch
---

`agentsmesh check` now gives the fix that matches the drift it found, instead of always saying "Run 'agentsmesh merge' to resolve, or 'agentsmesh generate --force' to accept current state." For canonical or generated-output drift (including the stale hashes a `merge` can leave) it points to plain `agentsmesh generate`; only changed locked features (`collaboration.strategy: lock`) get the `generate --force` advice. A `.agentsmesh/.lock` with git conflict markers is now reported as a lock conflict with the `agentsmesh merge` fix (and `lockConflict: true` in `--json`, in the MCP `check` tool result, and in the `LockSyncReport` returned by the programmatic `check()`), instead of "Not initialized for collaboration".
15 changes: 15 additions & 0 deletions .changeset/lessons-cli-input-papercuts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'agentsmesh': patch
---

The `agentsmesh lessons` commands handle bad input clearly instead of quietly doing the wrong thing.

A flag that needs a value but gets none now fails with exit 2 and "--flag needs a value". Before, it was ignored: `deprecate X --superseded-by` deprecated without the supersede link, and `query --session` skipped dedup. A value that starts with `--` can be passed as `--flag=value` (for example `--rule="--no-verify is forbidden"`), and the error for an unknown "flag" that is really text says so. `prune --cap abc` no longer falls back to the default cap. `lessons help [subcommand]` works.

`lessons add` uses exit 2 for every input error, with messages that name the flag: `--scope` other than `always`, a topic id that is not kebab-case (it suggests one), `--new-topic` without a non-blank `--topic-summary`, and an unsafe `--trigger-file` glob, which is now refused before any trigger id is made. A change the graph validator refuses also exits 2, and the message is plain: `Refused to save the lessons graph: … Nothing was written.` Internal names such as `mutateLessonsGraph:` no longer show in messages. Repeated `--evidence` refs are stored once. The 2000-character rule limit counts characters, so an emoji counts once.

`--trigger-file` is stored in one form: surrounding spaces and a leading `./` are dropped, so `./src/a.ts` reuses the `src/a.ts` trigger. A relative path that climbs out of the project (`../x.ts`), the project root, or an existing folder is rejected with a clear reason; for a folder it suggests `folder/**`. The same applies to the MCP `lessons_add` tool. A `--trigger-cmd` with a `\u{…}` escape is rejected, as the docs said.

`query` says when a legacy `index.yaml` store could not be migrated, instead of printing only "(no matches)". `import-md --migrated-at` must be a real date. `AGENTSMESH_LESSONS_TELEMETRY` and `AGENTSMESH_LESSONS_OUTCOME_LOG` also accept `true`/`false`, `yes`/`no` and `on`/`off`. `lessons query` warns when `config.json` has a switch that is not `true`/`false` (such as `"outcomeLog": "no"`) or is not a JSON object.

Smaller fixes: `show <lesson>` includes the rationale, `journal` marks deprecated and superseded lessons, `validate --json` names the error codes, messages end with a period, the `--ids` help text says what it does, and the docs keyword example uses one `--trigger-kw` per keyword.
11 changes: 11 additions & 0 deletions .changeset/lessons-hook-merge-log-edges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'agentsmesh': patch
---

The lessons recall hook, the lessons.json merge driver and the lessons logs handle more edge cases correctly.

Recall hook: it reads a payload over 1 MB to the end before ignoring it, so the host no longer gets a broken pipe, and it reads JSON that starts with a UTF-8 BOM. An event name it does not know (such as Gemini's `BeforeTool`) now does nothing instead of answering as `PostToolUse`; a payload with no event name is still a tool call. Copilot's VS Code compatible `SessionStart` (with `initial_prompt`) gets task recall. The project now comes from the touched file first, so in a monorepo a package's own lessons apply to its files, and a `cwd` outside the project no longer hides it. A decomposed (NFD) path matches its glob. On a prompt, the note about hidden matches is back: at most 5 keyword rules are shown, the always-on lessons keep their own budget, and the hook says what either cap left out. The recurrence warning counts only failures from the last 24 hours (it used to count every failure ever, "failed 833×"). A Cursor `permission_denied` is not recorded as a failure, a failed command's nudge no longer suggests a file glob, and recalls running at the same time no longer lose each other's session dedup entries.

Logs and files: an append after a line cut off mid-write starts a new line instead of gluing two records, the logs are capped by size (a single huge line is dropped) and readers read only the newest part, a read-only `lessons.json` is not written over and a save keeps its file mode, a `.lessons.lock` that is a file gets a clear message instead of `ENOTDIR`, a UTF-8 BOM in `lessons.json` or `config.json` is ignored, a writer waiting on a busy lock says once who holds it, and old temp files and stale lock folders are cleaned up.

Merge: a trigger or topic deleted on one branch stays deleted when the other branch did not change it and no lesson uses it. `lessons resolve` refuses to save a result with errors when it had to rebuild the sides from conflict markers (and keeps the markers), warns when the markers have no merge base, counts lessons after same-id renames, and names the right next step for a merge, rebase, cherry-pick or revert (none outside git). The merge driver falls back to the bare command when npx is missing but agentsmesh is on PATH. `init` and `generate` ask you to re-run `init --lessons` when the recall hook command in hooks.yaml no longer matches the project's agentsmesh dependency, and `generate` no longer repeats "Kept your own lessons.json merge driver" on every run.
9 changes: 9 additions & 0 deletions .changeset/local-pack-reinstall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'agentsmesh': patch
---

Installing a changed pack again now updates it in place. Before, if the source dropped a folder (say `commands/`), running `agentsmesh install` again with the same `--name` failed with "Auto-generated pack name … collides", and without `--name` it added a second pack from the same source that kept the removed files. Now the install finds the pack from the same source, `--target` and `--as` (by `--name`, by feature set, or the one pack that covers the whole source). When both cover the whole source, it replaces the pack's contents like `refresh`, so files removed at the source go away. A picked subset still merges, and packs split by `--path`, `--as` or pick stay separate. A re-install without `--name` also keeps the pack's name (it used to rename a local pack to an auto-generated name), and `--dry-run` shows the pack it would update. A `--name` that belongs to a pack from another source now fails with a clear message that names the pack.

Skill folders are no longer dropped because of their name. A source with `rules/` next to `skills/my_skill/` or `skills/S1/` used to look like a lone rules folder, so its skills, README and LICENSE were skipped without a word. Any skill folder name now counts, except names that start with `.` or `_`.

`mcp.json`, `hooks.yaml`, `permissions.yaml` and `ignore` at the root of a source without `.agentsmesh/` are still not installed (settings install only from a source's `.agentsmesh/` folder), but install now prints one warning that names each skipped file.
5 changes: 5 additions & 0 deletions .changeset/mcp-check-generate-parity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'agentsmesh': patch
---

The MCP `check` and `generate` tools now tell the same story as the CLI. `check` runs the same check as `agentsmesh check`, so an unreadable `.agentsmesh/lessons/lessons.json` (a merge conflict, bad JSON, a schema error or a newer version) is now reported in a new `lessonsGraphError` field, with the same text as the CLI JSON `error`, instead of looking like a clean result. `generate` sets `lockfileUpdated` only when the run really rewrote `.agentsmesh/.lock`; a run that changes nothing leaves the lock alone and now says `false`.
5 changes: 5 additions & 0 deletions .changeset/olive-eels-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'agentsmesh': patch
---

Internal-only: removed dead code and collapsed duplicated generators. Two exported helpers had no caller outside their own tests since the commit that introduced them, and one install helper was fully superseded by a more general sibling. Fifteen targets each carried the same four-line ignore generator differing only in a path constant, and the pack writer and merger each repeated the same copy-into-subdirectory loop three times; both now call one shared helper. No behaviour changes: every generated artifact is byte-identical.
9 changes: 9 additions & 0 deletions .changeset/plain-moons-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'agentsmesh': minor
---

The MCP server now tells every client about lessons when it connects, and says something true in both states.

Where a project has lessons, the server hands over the same recall and capture contract that `init --lessons` writes into your instruction file. That matters for a plugin: a plugin can ship skills and servers but never your instruction file, so a plugin-only install previously had no standing instruction at all and recall depended on the agent opening the skill first. The obligations are phrased in tool names rather than shell commands, since a client reaching the server this way may have no shell.

Where a project has no lessons, the server says so plainly and explains how to start one. It does not name a graph file you do not have, does not point at a skill you never installed, and mandates nothing. This matters because the server also carries the configuration tools and is documented on its own: most people who wire it up never opted into lessons, and they should not be told to query a memory that cannot answer.
5 changes: 5 additions & 0 deletions .changeset/stable-lock-noop-generate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'agentsmesh': patch
---

`agentsmesh generate` no longer rewrites `.agentsmesh/.lock` when nothing changed. Before, a run that printed "Nothing changed" still wrote a new `generated_at`, so the git tree was dirty after every `generate` and each teammate's run showed a lock diff. Now the lock is rewritten only when its `checksums`, `extends`, `packs` or `outputs` change; otherwise the file stays byte-for-byte the same. `generated_at`, `generated_by` and `lib_version` now describe the last run that changed the lock. `check`, `generate --check` and `watch` work as before.
13 changes: 13 additions & 0 deletions .changeset/steady-lessons-hold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'agentsmesh': minor
---

Lessons now hold up for teams, for more tools, and against a graph you did not write yourself.

Teams: two branches that both capture lessons now merge cleanly. The git merge driver merges each lesson field by field, and every clone gets the driver the next time it runs `agentsmesh generate` (or `init --lessons`), so it no longer depends on one person's setup. If a merge still leaves conflict markers, the new `agentsmesh lessons resolve` combines both sides. `agentsmesh check` and `generate --check` now fail when `lessons.json` cannot be read (a merge conflict, a corrupt file, a newer schema), instead of passing while recall is silently off. The lessons lock no longer loses a lesson when many agents write at once. A fresh clone no longer prunes lessons whose files are merely not created yet: a glob counts as dead only when git history shows its file was deleted or renamed. Generated recall hooks run `npx --no --offline agentsmesh` when the project depends on agentsmesh, so teammates without a global install still get recall.

More tools: the recall hook now answers Gemini CLI's `BeforeAgent`, Cursor's `sessionStart` and `postToolUseFailure`, and GitHub Copilot's `sessionStart` and `postToolUseFailure`. Codex `apply_patch` edits get recall for the files they touch, subagents get their own session dedup, and the hook and MCP server find the lessons project from a subdirectory. Target descriptors (including plugins) can declare `hookContextEvents` so recall is only wired to events whose output reaches the model.

Capture and effectiveness: failures are read from the field Claude Code actually sends, keyed on the command that really ran, and user interrupts are no longer counted. A `--trigger-file` path outside the project is rejected instead of being stored where it could never fire. The outcome log is on by default (turn it off with `"outcomeLog": false` in `.agentsmesh/lessons/config.json` or `AGENTSMESH_LESSONS_OUTCOME_LOG=0`), and a lesson counts as missed only when the same action fails again in the same session within 30 minutes, so `validate` and `stats` stop flagging lessons that work.

Safety: recalled rules are delivered one per line inside a `<recalled-lessons>` block, with ids, and every CLI and MCP answer is size-capped, so a hostile rule cannot pose as a system message or flood the context. `file_glob` triggers use a linear-time matcher over a safe glob subset; other glob syntax is rejected with `UNSAFE_GLOB_PATTERN` and never matches, so a crafted glob can no longer stall recall. `recallLimit` and `recallMaxTokens` in config.json are capped at 50 and 8000, `lessons query --always` has the same budget as the hook, and legacy migration refuses index paths outside `.agentsmesh/lessons/`.
13 changes: 13 additions & 0 deletions .changeset/upgrade-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'agentsmesh': minor
---

**Upgrade notes.** Most projects need to do nothing, but check these after you upgrade:

- Run `agentsmesh generate` once. Hooks for Gemini CLI, GitHub Copilot, Cursor and Windsurf, lessons recall hooks, and hooks from installed packs can be generated differently now, so `agentsmesh generate --check` reports drift until you regenerate.
- Run `agentsmesh lessons validate`. Some lesson file triggers no longer match anything, and `lessons validate` and `agentsmesh lint` now report them as `UNSAFE_GLOB_PATTERN` errors: `**` inside a name (`src/**.ts`, write `src/**/*.ts`), extglobs (`+(a|b)`, write `{a,b}`) and ranges (`{1..3}`, write `{1,2,3}`).
- Gemini CLI hooks match exact tool names now. `Bash`, `Edit`, `Write` and `Read` reach Gemini's own tools (before, they matched nothing there), but a partial Gemini name such as `shell` no longer matches: use the full name (`run_shell_command`) or the Claude Code name (`Bash`). A `UserPromptSubmit` hook now also runs on Gemini, as `BeforeAgent`.
- `SessionStart` and `PostToolUseFailure` hooks now also reach GitHub Copilot, and `PostToolUseFailure` hooks reach Cursor.
- The lessons outcome log (`.agentsmesh/lessons/outcome-log.jsonl`, local and gitignored) is on by default, and turning telemetry off no longer stops it. Turn it off with `"outcomeLog": false` in `.agentsmesh/lessons/config.json` or `AGENTSMESH_LESSONS_OUTCOME_LOG=0`.
- `agentsmesh lessons` exits 2 for a flag with an empty value, so a script that runs `--cmd "$CMD"` fails when `CMD` is empty.
- Installing the same whole source again rebuilds its pack, so files you added by hand inside `.agentsmesh/packs/<name>/` are removed, as `refresh` already did. Keep your own changes in `.agentsmesh/`, outside `packs/`.
Loading
Loading