Add agents_md profile field for AGENTS.md content appending - #82
Merged
Conversation
The base AGENTS.md is shared across all agents and profiles with no way to add profile-specific context (e.g., work VPN hints, team tooling). New `agents_md` field on profiles accumulates through the inheritance chain (parent first, child appends) and is merged with the base file at install time, written atomically to `~/.ai-agent-rules/cache/shared/AGENTS.md`, and symlinked from `~/AGENTS.md`. All other agents resolve transitively through `~/AGENTS.md` via `@` includes so no per-agent changes are needed. Also fixes CodexAgent, which was the only agent pointing its AGENTS.md symlink directly at the base file instead of using `@~/AGENTS.md` like every other agent.
Mypy flagged `get_merged_agents_md_path()` returning `Path | None` in the `symlinks` property — assert non-None when `needs_agents_md_cache` is true (the two conditions are logically equivalent). E2E fixture was missing `codex/AGENTS.md` in the config dir, same gap already fixed in the unit conftest.
wpfleger96
force-pushed
the
worktree-wpfleger-agents-md-profile-merge
branch
from
June 4, 2026 16:51
1f565d2 to
76e1551
Compare
wpfleger96
marked this pull request as ready for review
June 4, 2026 16:51
…che diff The Rich-formatted unified diff logic was duplicated verbatim between get_content_diff() and get_cache_diff(). Extract into a single format_unified_diff() helper in symlinks.py, refactor all three callers (symlinks, targets, MCP), and wire up AgentsMdComponent to show actual content diffs instead of just "stale." MCP diffs now get the same green/red coloring as all other components. Also adds agents_md content to the work profile for VPN/uv hints.
- Fix MCP format_diff argument order (installed→expected, not reversed) and restore dropped server name header in diff output - Fix ctx.console → console in MCP status to respect output buffering - Extract get_expected_agents_md_content() on SharedAgent, eliminating 3x duplicated merge logic and handling empty base AGENTS.md correctly - Simplify is_agents_md_cache_stale() to pure content comparison, removing mtime checks with parent-profile blind spot - Auto-include SharedAgent in filtered installs (--agents codex) since all agents depend on ~/AGENTS.md via @-includes - Add agents_md to README profile key documentation - Fix ruff format-check CI failure
wpfleger96
added a commit
that referenced
this pull request
Jun 4, 2026
* feat: add Sprout persona pack symlink management The Sprout persona pack living in src/ai_rules/config/sprout/ had no install logic — the pack only reached Sprout via manual UI import, which copies files and breaks the single-source-of-truth managed by ai-rules. Adds a SproutTool target that symlinks the pack directory into both the production (xyz.block.sprout.app) and dev (xyz.block.sprout.app.dev) Sprout Application Support paths on macOS. Worktree dev builds inherit automatically via Sprout's own shared-agent-data symlink mechanism, so no additional targets are needed. Also fixes _is_specialized_path() in ConfigComponent to gate on isinstance(target_owner, Agent) rather than substring-matching path strings — the old check would have silently filtered Sprout's pack paths (which contain /agents/) from the config install pipeline. * Add agents_md profile field for AGENTS.md content appending (#82) * feat: add agents_md profile field for AGENTS.md content appending The base AGENTS.md is shared across all agents and profiles with no way to add profile-specific context (e.g., work VPN hints, team tooling). New `agents_md` field on profiles accumulates through the inheritance chain (parent first, child appends) and is merged with the base file at install time, written atomically to `~/.ai-agent-rules/cache/shared/AGENTS.md`, and symlinked from `~/AGENTS.md`. All other agents resolve transitively through `~/AGENTS.md` via `@` includes so no per-agent changes are needed. Also fixes CodexAgent, which was the only agent pointing its AGENTS.md symlink directly at the base file instead of using `@~/AGENTS.md` like every other agent. * fix: resolve CI failures from agents_md feature Mypy flagged `get_merged_agents_md_path()` returning `Path | None` in the `symlinks` property — assert non-None when `needs_agents_md_cache` is true (the two conditions are logically equivalent). E2E fixture was missing `codex/AGENTS.md` in the config dir, same gap already fixed in the unit conftest. * refactor: extract shared format_unified_diff and wire up AGENTS.md cache diff The Rich-formatted unified diff logic was duplicated verbatim between get_content_diff() and get_cache_diff(). Extract into a single format_unified_diff() helper in symlinks.py, refactor all three callers (symlinks, targets, MCP), and wire up AgentsMdComponent to show actual content diffs instead of just "stale." MCP diffs now get the same green/red coloring as all other components. Also adds agents_md content to the work profile for VPN/uv hints. * fix: address crossfire review feedback for agents_md PR - Fix MCP format_diff argument order (installed→expected, not reversed) and restore dropped server name header in diff output - Fix ctx.console → console in MCP status to respect output buffering - Extract get_expected_agents_md_content() on SharedAgent, eliminating 3x duplicated merge logic and handling empty base AGENTS.md correctly - Simplify is_agents_md_cache_stale() to pure content comparison, removing mtime checks with parent-profile blind spot - Auto-include SharedAgent in filtered installs (--agents codex) since all agents depend on ~/AGENTS.md via @-includes - Add agents_md to README profile key documentation - Fix ruff format-check CI failure * refactor: read Sprout pack ID from plugin.json instead of hardcoding The pack ID was hardcoded as SPROUT_PACK_ID in platform.py, coupling ai-rules to a specific pack. Now SproutTool reads the id field from .plugin/plugin.json at runtime, so any pack definition dropped into config/sprout/ works without code changes. Gracefully returns no symlinks if the manifest is missing or malformed. * style: apply ruff formatting to sprout.py * chore: remove unused avatar PNG source files from sprout pack Avatars are already base64-encoded inline in the persona .persona.md frontmatter. The raw PNGs in avatars/ were unreferenced by any pack file and added 756 KB of dead weight.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds an
agents_mdfield to profiles that appends profile-specific content to the baseAGENTS.mdat install time, enabling per-profile agent hints (e.g., work VPN instructions, team-specific tooling).AGENTS.mdwas previously a pure symlink to a static base file shared identically across all profiles. There was no way to add profile-specific context without editing the base file directly. Content accumulates through the inheritance chain (parent first, child appends) sodefault → personal → worklayering works naturally.agents_md: str = ""toProfilewith inheritance accumulation, validation, and display inprofile show --resolvedSharedAgentbuilds a merged file (base AGENTS.md+ profile content) at~/.ai-agent-rules/cache/shared/AGENTS.mdand redirects~/AGENTS.mdthere whenagents_mdis truthy; all other agents resolve transitively via@~/AGENTS.mdincludesAgentsMdComponentmanages the cache lifecycle (build, staleness detection via content comparison, diff display, uninstall) as infrastructure beforeConfigComponent, consistent withSettingsComponentConfig.cleanup_orphaned_cacheinternally protectscache/shared/from deletion whenagents_mdis setCodexAgentto useconfig/codex/AGENTS.mdcontaining@~/AGENTS.md, aligning it with the indirection pattern every other agent already usesSharedAgentin filtered installs (--agents codex) since all agents depend on~/AGENTS.mdtransitivelyformat_unified_diff()insymlinks.pyas a shared helper for Rich-formatted unified diffs, replacing duplicated formatting loops inget_content_diff(),get_cache_diff(), andMcpManager.format_diff()format_diffargument order (installed→expected) and restore dropped server name header; fixctx.console→consolefor output bufferingagents_mdcontent with VPN/uv package resolution hints