bots-garden/mini-mepublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/bots-garden/mini-me.git
git clone ssh://git@rickub.com/bots-garden/mini-me.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

💾 Saved. d722711 · on main · k33g · 2h ago
history.md · 69 lines · 13.3 KBmarkdown
Blame HistoryOpen raw

History

One entry per session, appended, never rewritten.

2026-09-15 — Diátaxis documentation bootstrap (agent "riker")

  • Asked: /diataxis-doc — start documenting the project, excluding ./kits and ./tmp. Ran in parallel with another agent adding /new.
  • Changed: created docs/ (language selector) with full four-quadrant trees in docs/en/ and docs/fr/, identical file names: 1 tutorial, 4 how-to guides, 6 reference pages, 3 explanations per language, plus both indexes. Linked the /new how-to page and docs/diagrams/packages.drawio written by the other agent. No Go code touched.
  • Decisions: language "Both" taken from the methodical-dev convention (user unavailable, skill's mandatory question skipped and recorded here). Shipped skill layout defect documented in how-to/reference rather than fixed.
  • Verified: go build OK; banner output for both YAML files captured verbatim; go test ./... fails on mm/internal/skills (test points at ../../../demo/skills). All relative links in docs/ resolve.
  • Docs: everything under docs/. Created .memory/ skeleton.

2026-09-15 — /new slash command (terminal + ACP), quality gate set-up, first .memory/

  • Goal: add /new to the mm agent to clear the history and start a fresh session, in the terminal REPL and over ACP; exclude ./kits and ./tmp from the quality measurement. Run by agent "bob" via methodical-dev, autonomously (the user was not available for the skill's approval gates), while agent "riker" wrote the rest of docs/ in parallel.
  • Changes: new package internal/session (NewCommand, NewCommandName, IsNewCommand, Fresh, Forgotten) + tests; detector.Reset() + first tests for internal/detector; internal/agent/agent.go (/new handling, startNewSession, banner, if/elseswitch for staticcheck QF1003, both front ends now start from session.Fresh); internal/acp/acp.go (availableCommands, available_commands_update in NewSession, /new interception in Prompt, startNewSession, resetSession) + tests; main.go package list comment; .qlty/qlty.toml (created); .quality/ (2 runs); docs (below); .memory/ created.
  • Decisions: /new resets history + engine token count + loop detector (REPL); ACP keeps session id / cwd / allow-always; only /new advertised over ACP; notification sent inside NewSession before the response; the session import is aliased history inside internal/acp because that package already has a session type. Rejected: reusing compactHistory's "keep the detector" rule for /new (different situation: the task changes); creating a git worktree (all files untracked); fixing the pre-existing demo/skills test path (layout decision for the user).
  • Tests: go test ./... — all packages pass except the pre-existing internal/skills failure (TestShippedSkillsHaveDescriptions, path ../../../demo/skills). /new smoke-tested end to end: piped REPL prints 🆕 new session: 0 message(s) forgotten; scripted JSON-RPC client sees available_commands_update then the session/new response, and /new answered by an agent_message_chunk + end_turn.
  • Quality: gate FAIL, 2 iterations: warnings 69 → 67, smells 18 → 18, complexity 620 → 618. Fixed: ineffassign in the new test, staticcheck QF1003 in agent.go. Remaining findings are all pre-existing (osv on go.mod, errcheck, complexity of agent.Run etc.) and out of this change's scope. Nothing was excluded beyond kits/** and tmp/**; no threshold changed.
  • Docs: docs/{en,fr}/how-to/start-a-new-session.md (new); /new rows and ACP paragraphs in docs/{en,fr}/reference/slash-commands.md and acp.md (riker's pages, edited in place); links in both README.md indexes; docs/diagrams/packages.drawio (new, from go list) referenced from both explanation/architecture.md.

2026-09-15 — Zed config fix in the editor how-to (orchestrator)

  • Asked: the user reported that the Zed agent_servers snippet in the docs is insufficient — Zed requires "type": "custom" in the entry.
  • Changes: added "type": "custom" to the JSON block in docs/en/how-to/use-from-an-editor.md and docs/fr/how-to/use-from-an-editor.md; recorded the requirement under "Decisions in force" in summary.md.
  • Tests / quality: docs-only change, none run.

2026-09-15 — ACP: /new was invisible in Zed's slash menu (orchestrator)

  • Asked: the user reported that Zed lists commands for other ACP agents (docker agent) but shows "Available commands for mini-me: none" and rejects /new as unknown.
  • Cause: available_commands_update was sent inside NewSession, i.e. before the SDK wrote the session/new response. Zed keys sessions on the id in that response and drops updates for an unknown session id.
  • Changes: internal/acp/acp.goRun now builds the front via newFront(e, system, tools, w, r); the SDK writes to a responseWriter that runs a per-session hook once the response line carrying that session id has been written; NewSession registers the hook (context.WithoutCancel(ctx), the request context dies with the method) instead of calling SessionUpdate directly. acp_test.goTestResponseSessionIDMatchesOnlySessionResponses, TestAvailableCommandsAreSentAfterTheSessionNewResponse (drives the real SDK over pipes, reads the raw lines back). Docs: available_commands_update row in docs/{en,fr}/reference/acp.md; summary.md decision updated, the "Zed slash menu" unknown removed.
  • Rejected: a goroutine with a time.Sleep after NewSession returns (a race, just an unlikely one); sending the list on the first session/prompt (too late for the menu before the first message).
  • Tests: go test -race ./internal/acp -count=5 ok; go build ok; real binary over stdin shows the response line before the notification line.
  • Not verified: the menu in a real Zed (no Zed in the sandbox) — the user should retry.

2026-09-15 — ACP: /compact and /abort alongside /new (orchestrator)

  • Asked: the user confirmed /new now shows in Zed and asked for the same for /compact and /abort.
  • Changes: internal/acp/acp.gocompactCommand/abortCommand constants, isCommand, three advertised commands, /abort intercepted in Prompt before turnMu (abortTurn → shared cancelTurn, also used by Cancel), /compact after turnMu (compactSessioncompactHistory(ctx, s, cfg, summarize, explain) (line, compressed), engine-free and testable). internal/compact/compact.goResult.Report() plus kilo/seconds moved here from internal/agent/agent.go, which now prints res.Report(). Tests: TestAvailableCommandsMatchWhatPromptIntercepts, TestIsCommandTrimsAndRequiresExactMatch, TestCompactHistoryOutcomes (3 sub-tests), TestCancelTurnFiresOnlyWhenATurnIsInFlight; the wire-order test now compares against availableCommands(). Docs EN+FR: reference/slash-commands.md (ACP section became a table), reference/acp.md (session/new row, three session/prompt rows, commands table), how-to/use-from-an-editor.md (cancel + compress/restart bullets), how-to/manage-the-context-window.md.
  • Decisions: /quit stays terminal-only; /compact over ACP is always forced (no automatic compaction exists in the ACP front end, unchanged); /abort answers ⚠️ No generation in progress. when idle rather than erroring. Rejected: handling /abort under turnMu (it could never reach a running turn).
  • Tests: go test -race on acp/compact ok; full go test ./... still fails only on the pre-existing internal/skills path test. Real binary driven by a small JSON-RPC client: commands list new, compact, abort; /abort idle → ⚠️ No generation in progress.; /compact\n on an empty history → 🗜️ nothing to compact: 1 message(s), no turn older than the last 3; both end_turn.
  • Not verified: /abort against a real running generation (no model server in the sandbox) and the two new entries in Zed's menu.

2026-09-15 — mm killed on the user's Mac (orchestrator, diagnosis only)

  • Asked: running mm on the Mac prints [1] 55918 killed mm.
  • Findings: the repo's ./mm is a Mach-O (magic CF FA ED FE), so the user rebuilt natively after the sandbox builds (the sandbox produced linux/arm64 ELF binaries at the same path in between — mm is gitignored, fine). SIGKILL of a freshly built Go binary on macOS is the invalid-signature kill; most likely cause is install.sh overwriting /usr/local/bin/mm IN PLACE with cp (the kernel keeps the old inode's signature cached → Killed: 9), possibly compounded by the repo living in a kDrive-synced folder. Not verifiable from the sandbox.
  • Proposed, not applied: sudo rm /usr/local/bin/mm && ./install.sh; make install.sh remove the target (or use install) before copying; codesign -vv /usr/local/bin/mm to confirm.

2026-09-15 — "the agent does not see the skills" (orchestrator, diagnosis only)

  • Cause confirmed in code: skills.List globs <skillsDir>/*.md and skills.Read opens <skillsDir>/<name>.md, while the shipped skills live in skills/<name>/SKILL.md — so skills: 0 and read_skill is never declared. Two aggravating factors: in terminal mode a relative skillsDir resolves against the current directory, and agent.yaml has been renamed agent.dmr.yaml by the user (no ./agent.yaml → built-in defaults; a Zed AGENT_CONFIG still pointing to agent.yaml names a missing file, which config.Load treats as an error).
  • Proposed, not applied: make List/Read accept both layouts (*.md and */SKILL.md, name = directory), fix the test path ../../../demo/skills../../skills.

2026-09-15 — Skills layout fix, skillsDir resolution, /abort removed from ACP (orchestrator)

  • Asked: fix the skills loader; make an installed mm (/usr/local/bin) load the skills of the directory it is started from; drop /abort from ACP because Escape already cancels in Zed.
  • Changes: internal/skills/skills.goList globs both <dir>/*.md and <dir>/*/SKILL.md, defaultName uses the directory name for a SKILL.md, Read tries <name>.md then <name>/SKILL.md (flat wins); tests TestListAcceptsFlatAndNestedLayouts, TestReadAcceptsFlatAndNestedLayouts, shipped-skills test path → ../../skills. main.goresolveSkillsDir(dir, configPath, acpMode) makes a relative skillsDir absolute from the current directory (terminal, or ACP without config) or next to the config file (ACP with one); a [warning: no skills found in <abs path> (expected <name>.md or <name>/SKILL.md there)] line when the count is 0. internal/acp/acp.go/abort handling, abortTurn, cancelTurn removed; Cancel back to its inline form; availableCommands() = new, compact; tests adjusted. Docs EN+FR: how-to/add-a-skill.md, reference/skill-format.md, reference/tools.md, reference/configuration.md, reference/cli.md, how-to/use-from-an-editor.md, reference/slash-commands.md, reference/acp.md. summary.md: known defects closed, skills decision added, ACP commands decision updated.
  • Decisions: both layouts accepted rather than moving the shipped files (the <name>/SKILL.md form is the Agent Skills convention); flat file wins when both exist; the warning is printed whenever 0 skills are found, with the resolved absolute path, because "skills: 0" alone was the user's whole problem.
  • Tests: go test -race ./... all green (first time internal/skills passes). Linux build to /tmp/mm-linux (NOT ./mm, which is the user's Mach-O): from the repo root the banner lists read_skill; from /tmp it warns no skills found in /tmp/skills.
  • Not verified: the Mac binary — the user must rebuild natively (sudo rm /usr/local/bin/mm && ./install.sh).

2026-09-15 — @path notation in questions (orchestrator)

  • Asked: mini-me must understand @path/file in a question, without a picker.
  • Changes: new internal/mention (Expand(input, cwd) (string, []Attachment), Attachment.Line()): mentions start the input or follow a space/bracket/quote, end at a space, lose trailing punctuation; resolved against cwd, absolute, or ~/; only existing paths attach, once each, as [attached file: …] / [attached directory: …] lines appended to the text (same shape as ACP resource_link). Wired in internal/agent/agent.go (cwd captured once in Run; 📎 <abs> dim line per attachment) and internal/acp/acp.go (after flatten, against s.cwd; [acp] session <id>: attached <path> on stderr). Tests: 4 in mention_test.go. Docs EN+FR: new how-to/attach-a-file.md, README indexes, reference/slash-commands.md (new @path section), reference/acp.md (prompt content row), how-to/use-from-an-editor.md, explanation/architecture.md package table, docs/diagrams/packages.drawio (node + edges from agent and acp).
  • Decisions: keep the sentence as typed and append the marker lines rather than rewriting the @ token (mirrors what Zed sends: text + resource_link); no inlining of content (bash-first agent reads it); paths with spaces unsupported (documented); non-existing paths silently left alone rather than warned (a @handle in a sentence is normal text).
  • Tests: go test -race ./... all green. Linux build in /tmp: typing explain @main.go and @internal, not @nothing.go prints two 📎 lines and none for the missing path.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# History

One entry per session, appended, never rewritten.

## 2026-09-15 — Diátaxis documentation bootstrap (agent "riker")

- **Asked:** `/diataxis-doc` — start documenting the project, excluding `./kits` and `./tmp`. Ran in parallel with another agent adding `/new`.
- **Changed:** created `docs/` (language selector) with full four-quadrant trees in `docs/en/` and `docs/fr/`, identical file names: 1 tutorial, 4 how-to guides, 6 reference pages, 3 explanations per language, plus both indexes. Linked the `/new` how-to page and `docs/diagrams/packages.drawio` written by the other agent. No Go code touched.
- **Decisions:** language "Both" taken from the methodical-dev convention (user unavailable, skill's mandatory question skipped and recorded here). Shipped skill layout defect documented in how-to/reference rather than fixed.
- **Verified:** `go build` OK; banner output for both YAML files captured verbatim; `go test ./...` fails on `mm/internal/skills` (test points at `../../../demo/skills`). All relative links in `docs/` resolve.
- **Docs:** everything under `docs/`. Created `.memory/` skeleton.

## 2026-09-15 — `/new` slash command (terminal + ACP), quality gate set-up, first `.memory/`

- **Goal**: add `/new` to the `mm` agent to clear the history and start a fresh session, in the terminal REPL and over ACP; exclude `./kits` and `./tmp` from the quality measurement. Run by agent "bob" via `methodical-dev`, autonomously (the user was not available for the skill's approval gates), while agent "riker" wrote the rest of `docs/` in parallel.
- **Changes**: new package `internal/session` (`NewCommand`, `NewCommandName`, `IsNewCommand`, `Fresh`, `Forgotten`) + tests; `detector.Reset()` + first tests for `internal/detector`; `internal/agent/agent.go` (`/new` handling, `startNewSession`, banner, `if/else``switch` for staticcheck QF1003, both front ends now start from `session.Fresh`); `internal/acp/acp.go` (`availableCommands`, `available_commands_update` in `NewSession`, `/new` interception in `Prompt`, `startNewSession`, `resetSession`) + tests; `main.go` package list comment; `.qlty/qlty.toml` (created); `.quality/` (2 runs); docs (below); `.memory/` created.
- **Decisions**: `/new` resets history + engine token count + loop detector (REPL); ACP keeps session id / cwd / allow-always; only `/new` advertised over ACP; notification sent inside `NewSession` before the response; the `session` import is aliased `history` inside `internal/acp` because that package already has a `session` type. Rejected: reusing `compactHistory`'s "keep the detector" rule for `/new` (different situation: the task changes); creating a git worktree (all files untracked); fixing the pre-existing `demo/skills` test path (layout decision for the user).
- **Tests**: `go test ./...` — all packages pass except the pre-existing `internal/skills` failure (`TestShippedSkillsHaveDescriptions`, path `../../../demo/skills`). `/new` smoke-tested end to end: piped REPL prints `🆕 new session: 0 message(s) forgotten`; scripted JSON-RPC client sees `available_commands_update` then the `session/new` response, and `/new` answered by an `agent_message_chunk` + `end_turn`.
- **Quality**: gate FAIL, 2 iterations: warnings 69 → 67, smells 18 → 18, complexity 620 → 618. Fixed: `ineffassign` in the new test, staticcheck QF1003 in `agent.go`. Remaining findings are all pre-existing (osv on `go.mod`, errcheck, complexity of `agent.Run` etc.) and out of this change's scope. Nothing was excluded beyond `kits/**` and `tmp/**`; no threshold changed.
- **Docs**: `docs/{en,fr}/how-to/start-a-new-session.md` (new); `/new` rows and ACP paragraphs in `docs/{en,fr}/reference/slash-commands.md` and `acp.md` (riker's pages, edited in place); links in both `README.md` indexes; `docs/diagrams/packages.drawio` (new, from `go list`) referenced from both `explanation/architecture.md`.

## 2026-09-15 — Zed config fix in the editor how-to (orchestrator)

- **Asked**: the user reported that the Zed `agent_servers` snippet in the docs is insufficient — Zed requires `"type": "custom"` in the entry.
- **Changes**: added `"type": "custom"` to the JSON block in `docs/en/how-to/use-from-an-editor.md` and `docs/fr/how-to/use-from-an-editor.md`; recorded the requirement under "Decisions in force" in `summary.md`.
- **Tests / quality**: docs-only change, none run.

## 2026-09-15 — ACP: `/new` was invisible in Zed's slash menu (orchestrator)

- **Asked**: the user reported that Zed lists commands for other ACP agents (docker agent) but shows "Available commands for mini-me: none" and rejects `/new` as unknown.
- **Cause**: `available_commands_update` was sent inside `NewSession`, i.e. before the SDK wrote the `session/new` response. Zed keys sessions on the id in that response and drops updates for an unknown session id.
- **Changes**: `internal/acp/acp.go``Run` now builds the front via `newFront(e, system, tools, w, r)`; the SDK writes to a `responseWriter` that runs a per-session hook once the response line carrying that session id has been written; `NewSession` registers the hook (`context.WithoutCancel(ctx)`, the request context dies with the method) instead of calling `SessionUpdate` directly. `acp_test.go``TestResponseSessionIDMatchesOnlySessionResponses`, `TestAvailableCommandsAreSentAfterTheSessionNewResponse` (drives the real SDK over pipes, reads the raw lines back). Docs: `available_commands_update` row in `docs/{en,fr}/reference/acp.md`; `summary.md` decision updated, the "Zed slash menu" unknown removed.
- **Rejected**: a goroutine with a `time.Sleep` after `NewSession` returns (a race, just an unlikely one); sending the list on the first `session/prompt` (too late for the menu before the first message).
- **Tests**: `go test -race ./internal/acp -count=5` ok; `go build` ok; real binary over stdin shows the response line before the notification line.
- **Not verified**: the menu in a real Zed (no Zed in the sandbox) — the user should retry.

## 2026-09-15 — ACP: `/compact` and `/abort` alongside `/new` (orchestrator)

- **Asked**: the user confirmed `/new` now shows in Zed and asked for the same for `/compact` and `/abort`.
- **Changes**: `internal/acp/acp.go``compactCommand`/`abortCommand` constants, `isCommand`, three advertised commands, `/abort` intercepted in `Prompt` before `turnMu` (`abortTurn` → shared `cancelTurn`, also used by `Cancel`), `/compact` after `turnMu` (`compactSession``compactHistory(ctx, s, cfg, summarize, explain) (line, compressed)`, engine-free and testable). `internal/compact/compact.go``Result.Report()` plus `kilo`/`seconds` moved here from `internal/agent/agent.go`, which now prints `res.Report()`. Tests: `TestAvailableCommandsMatchWhatPromptIntercepts`, `TestIsCommandTrimsAndRequiresExactMatch`, `TestCompactHistoryOutcomes` (3 sub-tests), `TestCancelTurnFiresOnlyWhenATurnIsInFlight`; the wire-order test now compares against `availableCommands()`. Docs EN+FR: `reference/slash-commands.md` (ACP section became a table), `reference/acp.md` (`session/new` row, three `session/prompt` rows, commands table), `how-to/use-from-an-editor.md` (cancel + compress/restart bullets), `how-to/manage-the-context-window.md`.
- **Decisions**: `/quit` stays terminal-only; `/compact` over ACP is always forced (no automatic compaction exists in the ACP front end, unchanged); `/abort` answers `⚠️ No generation in progress.` when idle rather than erroring. Rejected: handling `/abort` under `turnMu` (it could never reach a running turn).
- **Tests**: `go test -race` on acp/compact ok; full `go test ./...` still fails only on the pre-existing `internal/skills` path test. Real binary driven by a small JSON-RPC client: commands list `new, compact, abort`; `/abort` idle → `⚠️ No generation in progress.`; ` /compact\n` on an empty history → `🗜️ nothing to compact: 1 message(s), no turn older than the last 3`; both `end_turn`.
- **Not verified**: `/abort` against a real running generation (no model server in the sandbox) and the two new entries in Zed's menu.

## 2026-09-15 — `mm` killed on the user's Mac (orchestrator, diagnosis only)

- **Asked**: running `mm` on the Mac prints `[1] 55918 killed mm`.
- **Findings**: the repo's `./mm` is a Mach-O (magic `CF FA ED FE`), so the user rebuilt natively after the sandbox builds (the sandbox produced linux/arm64 ELF binaries at the same path in between — `mm` is gitignored, fine). SIGKILL of a freshly built Go binary on macOS is the invalid-signature kill; most likely cause is `install.sh` overwriting `/usr/local/bin/mm` IN PLACE with `cp` (the kernel keeps the old inode's signature cached → `Killed: 9`), possibly compounded by the repo living in a kDrive-synced folder. Not verifiable from the sandbox.
- **Proposed, not applied**: `sudo rm /usr/local/bin/mm && ./install.sh`; make `install.sh` remove the target (or use `install`) before copying; `codesign -vv /usr/local/bin/mm` to confirm.

## 2026-09-15 — "the agent does not see the skills" (orchestrator, diagnosis only)

- **Cause confirmed in code**: `skills.List` globs `<skillsDir>/*.md` and `skills.Read` opens `<skillsDir>/<name>.md`, while the shipped skills live in `skills/<name>/SKILL.md` — so `skills: 0` and `read_skill` is never declared. Two aggravating factors: in terminal mode a relative `skillsDir` resolves against the current directory, and `agent.yaml` has been renamed `agent.dmr.yaml` by the user (no `./agent.yaml` → built-in defaults; a Zed `AGENT_CONFIG` still pointing to `agent.yaml` names a missing file, which `config.Load` treats as an error).
- **Proposed, not applied**: make `List`/`Read` accept both layouts (`*.md` and `*/SKILL.md`, name = directory), fix the test path `../../../demo/skills``../../skills`.

## 2026-09-15 — Skills layout fix, skillsDir resolution, `/abort` removed from ACP (orchestrator)

- **Asked**: fix the skills loader; make an installed `mm` (`/usr/local/bin`) load the skills of the directory it is started from; drop `/abort` from ACP because Escape already cancels in Zed.
- **Changes**: `internal/skills/skills.go``List` globs both `<dir>/*.md` and `<dir>/*/SKILL.md`, `defaultName` uses the directory name for a `SKILL.md`, `Read` tries `<name>.md` then `<name>/SKILL.md` (flat wins); tests `TestListAcceptsFlatAndNestedLayouts`, `TestReadAcceptsFlatAndNestedLayouts`, shipped-skills test path → `../../skills`. `main.go``resolveSkillsDir(dir, configPath, acpMode)` makes a relative `skillsDir` absolute from the current directory (terminal, or ACP without config) or next to the config file (ACP with one); a `[warning: no skills found in <abs path> (expected <name>.md or <name>/SKILL.md there)]` line when the count is 0. `internal/acp/acp.go``/abort` handling, `abortTurn`, `cancelTurn` removed; `Cancel` back to its inline form; `availableCommands()` = `new`, `compact`; tests adjusted. Docs EN+FR: `how-to/add-a-skill.md`, `reference/skill-format.md`, `reference/tools.md`, `reference/configuration.md`, `reference/cli.md`, `how-to/use-from-an-editor.md`, `reference/slash-commands.md`, `reference/acp.md`. `summary.md`: known defects closed, skills decision added, ACP commands decision updated.
- **Decisions**: both layouts accepted rather than moving the shipped files (the `<name>/SKILL.md` form is the Agent Skills convention); flat file wins when both exist; the warning is printed whenever 0 skills are found, with the resolved absolute path, because "skills: 0" alone was the user's whole problem.
- **Tests**: `go test -race ./...` all green (first time `internal/skills` passes). Linux build to `/tmp/mm-linux` (NOT `./mm`, which is the user's Mach-O): from the repo root the banner lists `read_skill`; from `/tmp` it warns `no skills found in /tmp/skills`.
- **Not verified**: the Mac binary — the user must rebuild natively (`sudo rm /usr/local/bin/mm && ./install.sh`).

## 2026-09-15 — `@path` notation in questions (orchestrator)

- **Asked**: mini-me must understand `@path/file` in a question, without a picker.
- **Changes**: new `internal/mention` (`Expand(input, cwd) (string, []Attachment)`, `Attachment.Line()`): mentions start the input or follow a space/bracket/quote, end at a space, lose trailing punctuation; resolved against cwd, absolute, or `~/`; only existing paths attach, once each, as `[attached file: …]` / `[attached directory: …]` lines appended to the text (same shape as ACP `resource_link`). Wired in `internal/agent/agent.go` (cwd captured once in `Run`; `📎 <abs>` dim line per attachment) and `internal/acp/acp.go` (after `flatten`, against `s.cwd`; `[acp] session <id>: attached <path>` on stderr). Tests: 4 in `mention_test.go`. Docs EN+FR: new `how-to/attach-a-file.md`, README indexes, `reference/slash-commands.md` (new `@path` section), `reference/acp.md` (prompt content row), `how-to/use-from-an-editor.md`, `explanation/architecture.md` package table, `docs/diagrams/packages.drawio` (node + edges from agent and acp).
- **Decisions**: keep the sentence as typed and append the marker lines rather than rewriting the `@` token (mirrors what Zed sends: text + resource_link); no inlining of content (bash-first agent reads it); paths with spaces unsupported (documented); non-existing paths silently left alone rather than warned (a `@handle` in a sentence is normal text).
- **Tests**: `go test -race ./...` all green. Linux build in `/tmp`: typing `explain @main.go and @internal, not @nothing.go` prints two `📎` lines and none for the missing path.