aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-16 05:58:14 -0500
committerCraig Jennings <c@cjennings.net>2026-05-16 05:58:14 -0500
commitd76efe15eb5718fb859df87ee12306bcbc56b07c (patch)
treeb9af43b4efed2116cb15f10100adb3a98a0682c4 /docs
parent99d93203a867294addf4927ceec5644b9d3bf322 (diff)
downloaddotemacs-d76efe15eb5718fb859df87ee12306bcbc56b07c.tar.gz
dotemacs-d76efe15eb5718fb859df87ee12306bcbc56b07c.zip
docs(design): three new gptel / agentic design notes
- gptel-git-tools-magit-backend.org -- spec for reimplementing the three current git_* tools on top of magit, plus three new tools (blame, show, branches). - gptel-agentic-tool-ideas.org -- brainstorm seed for additional agentic gptel tools. - agentic-knowledgebase.org -- design sketch for using org-roam as the agent's durable project memory with org-agenda as the execution layer.
Diffstat (limited to 'docs')
-rw-r--r--docs/design/agentic-knowledgebase.org117
-rw-r--r--docs/design/gptel-agentic-tool-ideas.org139
-rw-r--r--docs/design/gptel-git-tools-magit-backend.org192
3 files changed, 448 insertions, 0 deletions
diff --git a/docs/design/agentic-knowledgebase.org b/docs/design/agentic-knowledgebase.org
new file mode 100644
index 00000000..c8b53e70
--- /dev/null
+++ b/docs/design/agentic-knowledgebase.org
@@ -0,0 +1,117 @@
+ ** Org-roam project knowledgebase
+
+ Use org-roam as the agent's durable project memory, with org-agenda as the
+ execution layer. The important distinction:
+
+ - Org-roam stores current understanding, decisions, people, open questions,
+ source links, and project history.
+ - Org-agenda stores commitments that require action.
+ - Mail, Slack, telega, ERC, Magit, and AI session files remain the raw sources.
+ - The agent writes concise summaries with backlinks rather than dumping
+ transcripts into roam.
+
+ Each active project gets one hub node tagged =Project=. The hub is the place to
+ ask "what is going on?" and should stay skimmable:
+
+ #+begin_src org
+ #+TITLE: Project: Example
+ #+FILETAGS: Project Example
+
+ * Status
+ Current goal, live state, blockers, and near-term plan.
+
+ * Next Actions
+ ** TODO Email Alice about API credentials
+ SCHEDULED: <2026-05-18 Mon>
+ :PROPERTIES:
+ :CONTACT: Alice Smith
+ :CHANNEL: email
+ :SOURCE: [[id:thread-20260515-api-credentials]]
+ :END:
+
+ ** WAITING Bob to review staging diff
+ :PROPERTIES:
+ :CONTACT: Bob Lee
+ :CHANNEL: Slack
+ :SOURCE: [[id:thread-20260516-review-request]]
+ :END:
+
+ * People
+ - [[id:person-alice-smith][Alice Smith]] - owns API credentials
+ - [[id:person-bob-lee][Bob Lee]] - reviewer
+
+ * Decisions
+ - [[id:decision-20260516-service-account-auth][Use service account auth]]
+
+ * Threads
+ - [[id:thread-20260515-api-credentials][Slack: API credentials]]
+ - [[id:thread-20260514-contract-clarification][Email: contract clarification]]
+
+ * Log
+ ** 2026-05-16
+ - Implemented first pass of Magit review tool design.
+ - Need to ask Alice whether staging access exists.
+ #+end_src
+
+ Supporting nodes should be small and typed:
+
+ - =Person: Alice Smith= - contact preferences, projects, open loops, recent
+ context.
+ - =Decision: Use service account auth= - decision, rationale, alternatives,
+ source links.
+ - =Thread: Slack API credentials= - durable summary and link to the source
+ message.
+ - =Meeting: Example kickoff 2026-05-16= - attendees, decisions, tasks, links.
+ - =Problem: Import job timing out= - symptoms, experiments, current theory.
+ - =Artifact: PR 123= - purpose, review state, verification, follow-ups.
+ - =Runbook: Deploy Example= - operational steps and caveats.
+
+ Agent commands:
+
+ - =cj/agent-project-brief= - build a temporary Org buffer with project status,
+ blockers, next actions, recent commits, recent messages, and open agenda
+ items.
+ - =cj/agent-capture-current-context= - capture the current Magit section, mail
+ message, Slack thread, telega chat, ERC buffer, Dired file, source buffer, or
+ agenda item into the active project.
+ - =cj/agent-project-next-contact= - show who needs a reply, who the user is
+ waiting on, channel, deadline, and source link.
+ - =cj/agent-summarize-project-day= - append a dated project log entry and
+ create or update agenda TODOs.
+ - =cj/agent-link-to-project= - link the current org-roam node or captured item
+ to a selected project hub.
+ - =cj/agent-promote-to-decision= - turn a line, thread summary, or meeting note
+ into a decision node and backlink it to the project.
+
+ Contact tracking should live in both person nodes and actionable TODOs. Person
+ nodes preserve relationship context; agenda TODOs preserve obligations:
+
+ #+begin_src org
+ #+TITLE: Alice Smith
+ #+FILETAGS: Person Contact
+
+ * Context
+ Works on infra. Best channel: Slack for quick questions, email for approvals.
+
+ * Projects
+ - [[id:project-example][Project: Example]]
+
+ * Waiting On
+ ** WAITING Alice to confirm API credentials
+ SCHEDULED: <2026-05-18 Mon>
+ :PROPERTIES:
+ :PROJECT: Example
+ :CHANNEL: Slack
+ :SOURCE: [[id:thread-20260515-api-credentials]]
+ :END:
+ #+end_src
+
+ The agent should maintain a short "project memory contract":
+
+ - Never create a note unless it will be useful after the chat window is gone.
+ - Prefer backlinks to raw sources over copied transcripts.
+ - Convert "someone needs to do something" into a TODO with owner/channel/source.
+ - Keep project hub status current, but keep detailed history in dated log,
+ meeting, decision, problem, and thread nodes.
+ - Ask before changing TODO states, scheduling work, or drafting messages to
+ real people.
diff --git a/docs/design/gptel-agentic-tool-ideas.org b/docs/design/gptel-agentic-tool-ideas.org
new file mode 100644
index 00000000..1790c42c
--- /dev/null
+++ b/docs/design/gptel-agentic-tool-ideas.org
@@ -0,0 +1,139 @@
+• #+TITLE: Design: GPTel Git Tools and Magit Backend
+ #+AUTHOR: Craig Jennings
+ #+DATE: 2026-05-16
+ #+OPTIONS: toc:nil num:nil
+
+ * Status
+
+ Draft.
+
+ This document was created after the requested path was not present in
+ =docs/design=. It captures the apparent design center: make GPTel more useful
+ inside Magit and then broaden that into Emacs-native agents that can use this
+ configuration as their operating environment.
+
+ * Problem
+
+ =gptel-magit= currently gives this config useful Magit entry points:
+
+ - Generate a commit message from the staged diff.
+ - Create a commit from a generated message.
+ - Explain the diff at point.
+
+ That is valuable, but it is still a narrow "send this diff to the model"
+ workflow. The richer opportunity is to expose Git, Magit, Org, project state,
+ and this Emacs configuration's personal workflow tools as agent affordances.
+
+ The target agent should not treat Emacs as a text terminal. It should treat
+ Emacs as the user's live workspace: buffers, narrowed regions, Magit sections,
+ Org tasks, agenda state, roam notes, mail, compilation buffers, diagnostics,
+ and vterm sessions are all structured context.
+
+ * Existing Leverage
+
+ This configuration already has several pieces that make agent work more
+ interesting than generic filesystem tools:
+
+ - =ai-config.el= provides GPTel backends, model switching, saved
+ conversations, Org-formatted AI buffers, context management, local tools,
+ and =gptel-magit= bindings.
+ - =gptel-tools/= provides local filesystem and buffer tools with safety
+ features such as backups and trash moves.
+ - =reconcile-open-repos.el= scans active project roots, finds dirty repos,
+ pulls clean repos, and opens Magit for manual review.
+ - =ai-vterm.el= design work gives the agent project-scoped terminal sessions
+ that stay inside Emacs.
+ - Org modules provide agenda, capture, refile, org-roam, dailies, export,
+ reveal.js, org-noter, and org-drill.
+ - Mail modules provide =mu4e=, =org-msg=, contacts, account-specific mail
+ navigation, attachment workflows, and privacy toggles for remote content.
+ - Communication modules provide Telegram via =telega=, Slack via
+ =emacs-slack=, and IRC via ERC.
+ - File and shell modules provide Dirvish/Dired, Eshell, vterm, TRAMP-aware
+ shell navigation, file previews, rsync, wdired, and external-open helpers.
+ - Media modules provide EMMS/MPV music playback, M3U playlist management,
+ radio station entries, Dirvish-to-playlist integration, transcription,
+ video/audio recording, EWW, Elfeed, PDF, and EPUB workflows.
+ - Development modules provide project navigation, test/lint Makefile targets,
+ compilation buffers, coverage summaries, and profiling/debug docs.
+
+ * Magit Backend Ideas
+
+ ** Section-aware Git tools
+
+ Expose Magit sections as first-class GPTel tools. Instead of asking the model
+ to reason over plain diff text, let it request:
+
+ - Current Magit section type, heading, file, hunk range, and content.
+ - Sibling sections under the same file.
+ - Staged vs unstaged vs untracked status for the current repository.
+ - Commit metadata around the selected commit or branch.
+ - The exact staged patch that would be committed.
+
+ This would let prompts say "review the file section at point" or "explain this
+ hunk in the context of adjacent hunks" without manually copying context.
+
+ ** Commit intent workbench
+
+ Add a transient that builds a commit intentionally:
+
+ 1. Agent reads unstaged/staged changes.
+ 2. Agent proposes coherent commit groups.
+ 3. User selects groups in a Magit-style buffer.
+ 4. Agent stages those paths or hunks only after confirmation.
+ 5. Agent generates a message that reflects the selected intent.
+
+ This is more useful than a single commit-message generator because many working
+ trees contain two or three unrelated edits.
+
+ ** Patch narrative buffer
+
+ Generate an Org buffer that explains the change set as a reviewable narrative:
+
+ - "What changed" by subsystem.
+ - "Why it appears to have changed" inferred from names, tests, and docs.
+ - "Risk areas" with links back to Magit file sections.
+ - "Suggested verification" using local Makefile targets when present.
+
+ The value is not only explanation; it is a reusable artifact that can be pasted
+ into a PR description, saved with an AI session, or filed into org-roam.
+
+ ** Review-thread simulator
+
+ Before opening a PR, create a local review buffer with inline comments attached
+ to Magit diff positions. The agent writes comments as if reviewing someone
+ else's patch, but the UI stays local:
+
+ - Comments are grouped by severity.
+ - Each comment links to the file and line.
+ - Resolved comments can be checked off in Org.
+ - Accepted suggestions can be applied through the existing text-update tools.
+
+ This makes "review my diff" less ephemeral and avoids losing useful review
+ findings inside a chat transcript.
+
+ ** Rebase and conflict coach
+
+ When Magit enters a rebase, cherry-pick, merge, or conflict state, offer an
+ agent command that reads:
+
+ - Git operation state from =.git/=.
+ - Conflict markers in the worktree.
+ - Relevant commits from =git log --merge= or the rebase todo.
+ - The current Magit status sections.
+
+ The agent should explain the conflict in domain terms and propose a resolution
+ patch, but leave the actual edit and =git add= under explicit user control.
+
+ ** Regression archaeology
+
+ A Magit transient command could run a bisect-like reasoning workflow:
+
+ - Ask for a symptom and a known-good/known-bad range.
+ - Summarize candidate commits in small batches.
+ - Use tests or user-provided repro commands when available.
+ - Maintain a bisect journal in an Org buffer.
+
+ Even when the agent cannot run the whole bisect, it can keep the investigation
+ structured and preserve why each commit was judged good or bad.
+
diff --git a/docs/design/gptel-git-tools-magit-backend.org b/docs/design/gptel-git-tools-magit-backend.org
new file mode 100644
index 00000000..94fbb0ce
--- /dev/null
+++ b/docs/design/gptel-git-tools-magit-backend.org
@@ -0,0 +1,192 @@
+#+TITLE: Design: gptel git tools on a magit backend
+#+AUTHOR: Craig Jennings
+#+DATE: 2026-05-16
+
+* Status
+
+Draft. Supersedes the three current git-tool implementations
+(=gptel-tools/git_status.el=, =gptel-tools/git_log.el=,
+=gptel-tools/git_diff.el=) shipped in commit =ceeae9b5=. Trigger:
+Craig flagged that magit already does much of this and could carry
+the backend for more git tools cheaply.
+
+* Problem
+
+The three current git_* tools shell out to git directly via
+=process-file= and parse stdout. Each carries:
+
+- Its own =--is-inside-work-tree= path-validation step.
+- Its own =-c color.ui=false= color suppression workaround (`git
+ status' doesn't accept =--no-color= the way `git log' / `git diff'
+ do).
+- Boilerplate to set up a temp buffer, run =process-file=, capture
+ output, return the string.
+
+There's also an opportunity cost: adding more git context tools
+(=git_blame=, =git_show=, =git_branches=, etc.) would mean
+duplicating the same boilerplate per tool.
+
+* Wins from a magit backend
+
+Three concrete things magit provides:
+
+1. *Path validation via =magit-toplevel=.* One call replaces the
+ two-step =process-file= + =rev-parse --is-inside-work-tree=
+ check. Returns the working-tree root or nil.
+
+2. *Process plumbing via =magit-git-insert= / =magit-git-string= /
+ =magit-git-lines=.* These wrap git invocation with magit's
+ environment, encoding handling, and the right color posture.
+ Drops the per-subcommand color-flag bikeshedding.
+
+3. *Typed helpers for higher-level concepts* -- =magit-get-current-branch=,
+ =magit-list-branches=, =magit-rev-ancestor-p=, etc. Most
+ relevant for the *new* tools (branches, show, blame), not the
+ three we already wrote.
+
+What magit doesn't give us: high-level "give me status as a string"
+helpers. =magit-status= / =magit-log-current= etc. populate
+interactive magit buffers, not strings. For tool output we'd still
+call =magit-git-insert "status" "--short" "--branch"= and grab the
+buffer string. Same shape, less boilerplate.
+
+* Costs
+
+- *Magit loads on first invocation* of any git_* tool. Magit pulls
+ in transient, with-editor, magit-section, magit-core -- heavyweight.
+ Mitigation: lazy =(require 'magit)= inside each tool's function
+ body so cold-start Emacs sessions don't pay the cost unless the
+ user actually calls a git tool.
+- *Tools no longer portable* to a no-magit Emacs. Acceptable here
+ because magit is a non-negotiable in this config; a future
+ drop-in distribution would need to publish a magit-free fallback.
+
+* Proposed shape
+
+** Single-file module: =gptel-tools/git_tools.el=
+
+The current "one file per tool" convention exists because the
+existing tools share little. These six tools share a lot
+(validate-path, run-git, truncate-output), so a single file with
+shared helpers is more honest.
+
+** Shared helpers
+
+- =cj/gptel-git--toplevel-or-error PATH=
+ - Wraps =magit-toplevel=. Signals =user-error= when PATH escapes
+ HOME, doesn't exist, or isn't inside a working tree.
+ - Returns the resolved working-tree root on success.
+
+- =cj/gptel-git--insert ARGS...=
+ - Wraps =magit-git-insert= in a =with-temp-buffer=, returns
+ =buffer-string=. Single chokepoint for color / encoding / error
+ handling.
+
+- =cj/gptel-git--truncate TEXT MAX-BYTES=
+ - Caps output, appends a one-line truncation marker when
+ triggered.
+
+ Open question: consolidate the matching helper from =web_fetch.el=
+ (=cj/gptel-web-fetch--truncate=) and the
+ =cj/update-text-file--*= analogue into a shared
+ =cj/gptel-tools--truncate-bytes= in =system-lib.el=, or keep
+ per-tool.
+
+** Six tools
+
+| Name | Magit-flavored shape |
+|------------------+--------------------------------------------------------------------|
+| =git_status= | =magit-git-insert "status" "--short" "--branch"= |
+| =git_log= | =magit-git-insert "log" "--oneline" (format "-n%d" N) ?--since= |
+| =git_diff= | =magit-git-insert "diff" REF1 REF2 "--" FILE= (each optional) |
+| =git_blame= | =magit-git-insert "blame" "--line-porcelain" FILE [-L S,E]= |
+| =git_show= | =magit-git-insert "show" REF= (message + full diff) |
+| =git_branches= | =magit-list-branches= (optionally filtered by =--list PATTERN=) |
+
+Each tool:
+- Validates =path= via =cj/gptel-git--toplevel-or-error=.
+- Calls =cj/gptel-git--insert= with the appropriate args.
+- Truncates via =cj/gptel-git--truncate=.
+- Registered as a separate tool with =gptel-make-tool= for
+ description / argv clarity at the model side.
+
+** Caps
+
+| Tool | Default cap | Hard cap |
+|---------------+----------------+--------------|
+| =git_status= | uncapped | uncapped |
+| =git_log= | 100 commits | 100 commits |
+| =git_diff= | 500 KB | 500 KB |
+| =git_blame= | 500 KB | 500 KB |
+| =git_show= | 500 KB | 500 KB |
+| =git_branches=| uncapped | uncapped |
+
+=git_log='s cap is on commit count; the rest cap output bytes.
+
+** :confirm posture
+
+All six tools are read-only. Same posture as the current
+implementation: =:confirm nil= (the model can call them
+autonomously, since they can't mutate state). The current
+git_status / git_log / git_diff already ship with =:confirm nil= --
+keeping it.
+
+** Tests
+
+Single file =tests/test-gptel-tools-git-tools.el=, replacing the
+three current per-tool test files. Real temp git repos via
+=process-file= (same pattern as current tests). Coverage per tool:
+Normal / Boundary / Error.
+
+Rough count: ~12 shared-helper tests (validator, insert wrapper,
+truncate) + ~7 per tool × 6 tools = ~54 tests total.
+
+* Migration
+
+1. Delete =gptel-tools/git_status.el=, =git_log.el=, =git_diff.el=.
+2. Delete =tests/test-gptel-tools-git-status.el=,
+ =test-gptel-tools-git-log.el=, =test-gptel-tools-git-diff.el=.
+3. Create =gptel-tools/git_tools.el= containing all six tools +
+ shared helpers.
+4. Create =tests/test-gptel-tools-git-tools.el=.
+5. Update =cj/gptel-local-tool-features= in =modules/ai-config.el=:
+ replace the three =git_*= symbols with one =git_tools= symbol
+ (or six if each tool wants its own feature file -- decide during
+ implementation).
+6. Make sure =modules/ai-config.el= can re-load without breaking the
+ live gptel session if the old tool symbols are still registered
+ from a prior Emacs.
+
+* Risks
+
+| Risk | Mitigation |
+|-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------|
+| Magit load slows first git_* tool call | One-time hit per session, scoped to the tool's :function body. Acceptable for opt-in tools. |
+| Tool registration name collision with the old git_* symbols | Use distinct names (git_status / git_log / git_diff stay; new tools join them). Or remove + restart. |
+| =magit-toplevel= behavior on TRAMP / remote paths | Validator rejects paths outside HOME first, so TRAMP paths can't reach magit-toplevel. |
+| =git_blame= exposes code surfaces the model shouldn't read | =:confirm nil= is the wrong posture if blame is sensitive. Open question for review. |
+| =git_show= reveals past-self commit message wording | Same as blame -- low risk on personal repo, but worth flagging. |
+
+* Open questions
+
+1. Build all six tools in one push, or phase status/log/diff first
+ and add blame/show/branches in a follow-up? My read: one push.
+ The helpers are shared, marginal cost of three more tools is
+ small, and the model gets meaningfully more useful git context.
+2. Consolidate the output-truncation helper into =system-lib.el=,
+ touching =web_fetch.el= and =update_text_file.el= for a cleaner
+ API? Or defer that to a separate refactor commit?
+3. =git_blame= and =git_show= -- =:confirm nil= or =:confirm t=?
+ Personal repo lowers the stakes but the model could ask for
+ blame on /any/ file under HOME.
+4. Tool feature symbols: one =git_tools= entry in
+ =cj/gptel-local-tool-features=, or six (one per tool)?
+ Currently each tool lives in its own provide-symbol file. With
+ the single-file design we'd register one feature symbol that
+ loads all six.
+
+* Effort estimate
+
+M (1-3 hours). Helpers + six tool wrappers + ~50 tests + migration.
+Most of the time is test authoring; the production code is small
+because magit absorbs the boilerplate.