diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/design/agentic-knowledgebase.org | 117 | ||||
| -rw-r--r-- | docs/design/gptel-agentic-tool-ideas.org | 139 | ||||
| -rw-r--r-- | docs/design/gptel-git-tools-magit-backend.org | 192 |
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. |
