dotfiles/.agents/docs/extraction-history.md
Brydon DeWitt 83f456f25b fix(plugin): guard against undefined output.output for MCP tools
MCP tools don't populate output.output in the tool.execute.after hook —
the MCP content flows through OpenCode's internal parts pipeline instead.
This caused a crash: undefined is not an object (evaluating 'text.length')
in the truncate function.
2026-06-06 02:11:24 -04:00

39 KiB
Raw Permalink Blame History

Agent Infra Extraction — Handoff Plan

Status: Complete through Phase 5. Remnant reduced to BFF-overlay only. All phases executed and committed. See per-phase status below.

Goal: Move repo-agnostic agent infrastructure out of Remnant into ~/dotfiles/.agents/ (existing dotfiles repo), wire it into each tool's global config so every project inherits it automatically, and reduce Remnant's footprint to a small project-specific overlay (BFF reminder, project AGENTS.md). After this work, Remnant can get back to being a Remnant codebase instead of an agent-infra lab.

Forward-looking work (MFE bootstrap, kanban unification, per-session tmp capture, project.config.js extraction, llama-server module, MemPalace, eval scaffolding, agentic-framework research) has moved to dotfiles-agent-infra-roadmap.md. This doc now covers only the extraction itself and the post-extraction validation findings.


Decisions (confirmed with user)

Decision Value
Shared infra location ~/dotfiles/.agents/ (existing repo, matches user's dotfiles naming)
Sharing mechanism Inherit via global tool config; verify global+project plugins/hooks coexist additively
MCP server name Rename remnant-agentsall-agents (safe — only 4 string refs, no permission impacts)
Uncommitted files Already committed as-is on main (Phase 1 done)
Research docs Move to shared infra (general-purpose, useful to any project)
Modelfiles Leave for now; address later
Global Copilot config Yes — create ~/.vscode-server/data/User/prompts/ and add global MCP entry
Project-specific bits Only Remnant's root AGENTS.md + the BFF/apps/client/src/pages/ reminder
agent-infrastructure.md split Lossless — ~95% to shared, thin pointer + Remnant tradeoffs stay

What's shareable vs. project-specific

Shareable (moves to ~/dotfiles/.agents/):

  • .agents/AGENTS.md — agent-infra design principles
  • .agents/agents/*.md — brainstorm, build, orchestrator, research
  • .agents/skills/research.md — research methodology
  • .agents/hooks/*.sh — all six hook scripts (pre/post-tool-use, session-start, stop, pre-compact, user-prompt-submit) except the BFF reminder block in post-tool-use.sh
  • .agents/mcp/index.ts — MCP server (will be refactored to auto-discover agents/skills from sibling dirs)
  • .agents/frameworks/opencode/plugin.ts — OpenCode plugin harness
  • .agents/frameworks/github/hooks.json — Copilot harness config
  • docs/research/*.md (5 files) — ai-coding-best-practices, human-llm-interpretation-overlap, intent-interpretation-action-plan, llm-intent-interpretation, text-communication-interpretation
  • docs/explorations/text-intent-interpretation-research.md
  • docs/ai_architectures.md
  • docs/projects/agent-infrastructure.md — almost entirely shared knowledge (see "Lossless split" below)
  • docs/infra/LLAMA-SERVER-CUDA-WSL2.md — general llama.cpp/CUDA setup notes

Project-specific (stays in Remnant):

  • Root AGENTS.md (Remnant overview, package pointers, monorepo rules)
  • BFF reminder + apps/client/src/pages/ path checks (currently embedded in post-tool-use.sh)
  • Nested AGENTS.md files in apps/, packages/
  • verification.md, docs/TODO.md, docs/projects/* (other than the agent-infrastructure split-off)
  • The two .modelfile files — leave in .agents/ with a MODELFILES.md note

Verification gates (Phase 0 — COMPLETE)

  1. OpenCode plugin coexistence — additive; all hooks run in sequence. Global dir: ~/.config/opencode/plugins/ (not ~/.opencode/plugins/).

  2. OpenCode MCP merge — configs merge (not replace). Global mcp entries

    • project mcp entries both load; project-level keys win on conflicts.
  3. Copilot global hook support — EXISTS. User-level hooks dir: ~/.copilot/hooks/ (macOS/Linux) per GitHub Copilot hooks reference. Load order is additive: repo .github/hooks/*.json → user ~/.copilot/hooks/*.json → repo settings.json inline → user ~/.copilot/settings.json inline → plugins. Symlink ~/.copilot/hooks/agent-support.json → dotfiles hooks.json = global coverage. No per-project stub needed. (Initial finding was wrong — VS Code docs don't cover Copilot's own config surface; always check docs.github.com first.)

  4. VS Code global MCP~/.vscode-server/data/User/mcp.json (create via MCP: Open Remote User Configuration command or directly).

  5. OpenCode hook overlay — BFF reminder ships as a separate project-local plugin file. No merged copy of post-tool-use.sh needed.


Target layout

~/dotfiles/.agents/                       ← canonical shared infra
├── AGENTS.md                             ← from remnant/.agents/AGENTS.md
│                                            + "Research Discipline" section
│                                            for global lessons/practices
│                                            (framework-agnostic: Copilot,
│                                            OpenCode, Claude Code all load
│                                            AGENTS.md natively — no
│                                            tool-specific config needed)
├── INSTALL-NOTES.md                      ← Phase 0 findings
├── install.sh                            ← one-time setup script (idempotent)
├── agents/
│   ├── brainstorm.md
│   ├── build.md
│   ├── orchestrator.md
│   └── research.md
├── skills/
│   └── research.md
├── hooks/
│   ├── pre-tool-use.sh
│   ├── post-tool-use.sh                  ← BFF block removed
│   ├── session-start.sh
│   ├── stop.sh
│   ├── pre-compact.sh
│   └── user-prompt-submit.sh
├── frameworks/
│   ├── opencode/plugin.ts
│   └── github/hooks.json
├── mcp/
│   └── index.ts                          ← auto-discovers agents/skills/
└── docs/
    ├── agent-infrastructure.md           ← the moved 855-line doc
    ├── ai-coding-best-practices.md       ← from docs/research/
    ├── ai_architectures.md
    ├── human-llm-interpretation-overlap.md
    ├── intent-interpretation-action-plan.md
    ├── llm-intent-interpretation.md
    ├── text-communication-interpretation.md
    ├── text-intent-interpretation-research.md
    └── llama-server-cuda-wsl2.md

Global wiring (created/modified by install.sh):
~/.config/opencode/opencode.json             ← merge MCP entry
~/.config/opencode/AGENTS.md                 ← symlink → dotfiles AGENTS.md (OpenCode global rules)
~/.config/opencode/plugins/agent-support.ts  ← symlink → dotfiles plugin
~/.config/opencode/agents/                   ← symlinks → dotfiles agents/*.md (added in post-Phase-4 fix)
~/.copilot/hooks/agent-support.json          ← generated by install.sh with absolute dotfiles paths (not a symlink)
~/.vscode-server/data/User/prompts/          ← create dir (currently missing)
~/.vscode-server/data/User/mcp.json          ← global VS Code MCP registration

Remnant (post-extraction, actual):
remnant/
├── AGENTS.md                             ← unchanged
├── .agents/
│   ├── README.md                         ← "shared infra: ~/dotfiles/.agents"
│   ├── hooks/
│   │   └── post-tool-use-remnant.sh      ← BFF reminder only
│   ├── omnicoder.modelfile               ← archived
│   └── omnicoder2.modelfile              ← archived
│   ⚠️  MODELFILES.md not created (planned but skipped)
├── .github/hooks/agent-support.json      ← gitignored; BFF PostToolUse only
├── .vscode/mcp.json                      ← exa only (remnant-agents removed)
└── opencode.json                         ← mcp.remnant-agents removed;
                                            permission overrides retained

Note: .opencode/ was gitignored; deleted from filesystem (agents now global).

Phases

Phase 0 — Verify coexistence DONE

Resolved all five gates. INSTALL-NOTES.md not produced (findings inline above).

Phase 1 — Checkpoint Remnant DONE

Already committed on main.

Phase 2 — Populate ~/dotfiles/.agents/ DONE

  1. Copy (not move) shareable files from remnant/.agents/ into ~/dotfiles/.agents/. Add a "Research Discipline" section to ~/dotfiles/.agents/AGENTS.md for cross-tool meta-guidance (e.g. check docs.github.com first for Copilot configuration questions). This is the canonical home for global lessons — AGENTS.md is natively loaded by Copilot, OpenCode, and Claude Code. Never use tool-specific mechanisms (OpenCode instructions: config, VS Code .instructions.md files) for guidance that belongs in AGENTS.md.
  2. Copy docs/research/*.md (5 files), docs/explorations/text-intent-interpretation-research.md, docs/ai_architectures.md, docs/infra/LLAMA-SERVER-CUDA-WSL2.md into ~/dotfiles/.agents/docs/.
  3. Split docs/projects/agent-infrastructure.md (lossless):
    • Moves to ~/dotfiles/.agents/docs/agent-infrastructure.md: the entire current doc minus the items below. This includes hook architecture, model scale profiles, MCP protocol status, OpenCode verified facts, the testing plan, open issues — all general infra knowledge.
    • Stays in remnant/docs/projects/agent-infrastructure.md (rewritten to a thin pointer):
      • Reference link to the shared doc
      • Remnant-specific "Known Tradeoffs" row: "Instructions glob trimmed to root AGENTS.md only" + the api//client//core/ mitigation
      • Mention of BFF reminder hook and its Remnant scope
      • Any items currently open that have Remnant-specific test cases (e.g. item 31 mentions apps/api/package.json paths — generalize for shared doc; keep concrete Remnant examples as a Remnant section)
  4. Refactor mcp/index.ts: auto-discover agents/*.md and skills/*.md relative to the script location, instead of a hand-maintained registry. Removes a friction point when adding new agents/skills.
  5. Rename MCP server remnant-agentsall-agents in mcp/index.ts.
  6. Refactor hooks/post-tool-use.sh: remove the BFF + apps/client/src/pages/ block. Document the extension point (comment: "project-local additions live in a sibling hook file or repo-local override").
  7. Write install.sh:
    • Detects existing global config (idempotent re-run safe).
    • Creates missing dirs (~/.vscode-server/data/User/prompts/, ~/.copilot/hooks/, ~/.config/opencode/plugins/).
    • Symlinks plugin into ~/.config/opencode/plugins/agent-support.ts.
    • Generates ~/.copilot/hooks/agent-support.json with absolute paths to ~/dotfiles/.agents/hooks/*.sh (not a symlink — avoids needing per-project hook stubs for relative-path resolution).
    • Merges all-agents MCP entry into ~/.config/opencode/opencode.json via jq.
    • Writes ~/.vscode-server/data/User/mcp.json with the all-agents MCP entry.
  8. Commit to dotfiles repo. (Push wherever; local-only is fine.)

Divergences from plan: jq replaced with node (not universally available); install.sh step 1 generates Copilot hooks JSON with absolute paths (not a symlink) to avoid per-project relative-path resolution issues. Step 3 added post-Phase-4 to wire ~/.config/opencode/agents/.

Phase 3 — Run install.sh DONE

  • Symlinks and generated files verified.
  • Smoke tests passed: RESEARCH_PROMPT: OK, HOOK_BLOCK: OK.
  • Bug found and fixed: OpenCode uses tool name bash (not run_in_terminal); pre-tool-use.sh case statement updated in both repos.

Phase 4 — Strip Remnant DONE

  1. Deleted agents/, skills/, frameworks/, mcp/, AGENTS.md from .agents/
  2. .agents/hooks/ reduced to post-tool-use-remnant.sh only
  3. ⚠️ MODELFILES.md stub not created (skipped — low value)
  4. .vscode/mcp.json: remnant-agents dropped, exa retained
  5. opencode.json: mcp.remnant-agents removed, permission overrides kept
  6. AGENTS.md updated to reference ~/dotfiles/.agents/AGENTS.md
  7. Docs deleted from remnant/docs/ (research/, ai_architectures.md, etc.)
  8. agent-infrastructure.md rewritten as thin pointer
  9. .agents/README.md added
  10. Committed (daf53a3, 8a61128)

Post-phase fix: .opencode/ had dead symlinks (pointed to deleted .agents/frameworks/ and .agents/agents/). Was gitignored so not in git history. Fixed by wiring agents globally via install.sh step 3 (~/.config/opencode/agents/), then deleting .opencode/ from the filesystem.

Phase 5 — Verify Remnant still works DONE (automated checks)

  • npm run build:strict passes (2 scripts ran, 15 skipped via wireit cache)
  • All 6 shared hook scripts pass bash -n syntax check
  • post-tool-use-remnant.sh passes bash -n
  • ~/.config/opencode/agents/ wired with 4 symlinks → dotfiles
  • ~/.copilot/hooks/agent-support.json present (generated, absolute paths)
  • Remnant .agents/ contains only: README.md, hooks/, omnicoder*.modelfile
  • Live session checks (require manual restart): /research etc. slash commands, hook block in live session, BFF reminder injection, VS Code MCP all-agents connect

Notes (post-execution)

  • All rename touch points done: remnant-agentsall-agents in mcp/index.ts, opencode.json, .vscode/mcp.json, AGENTS.md.
  • <PostToolUse-context> block working as designed — injected to model only, not shown in chat transcript (see post-tool-use.sh line ~137).
  • Global Copilot hook mechanism confirmed: ~/.copilot/hooks/ exists and is additive with repo hooks. No per-project stubs needed when paths are absolute.

Out of scope (do later)

  • Salvaging omnicoder*.modelfile content into shared system-prompt references — user chose "leave for now."
  • Publishing dotfiles as a public agent-infra repo / npm package.
  • Refactoring hooks to be platform-agnostic (item 22 in the migrated agent-infrastructure.md) — track in the shared repo after extraction.
  • Make .agents/ TypeScript files conform to Remnant's ESLint rules — the additionalIgnores bypass added in Phase 2 is a shortcut, not a solution. .agents/mcp/index.ts and .agents/frameworks/opencode/plugin.ts use import.meta.url directly (blocked by no-restricted-syntax) and have minor unused-var patterns. Options: (a) replace import.meta.url usages with the approved findNearestPackageRoot / new URL('./sibling', import.meta.url) patterns where valid, (b) introduce a per-file exception comment for the genuinely exceptional cases (e.g. portable hook resolution in a symlinked global plugin), (c) move all .agents/ TS into a proper subpackage with its own tsconfig.json and relaxed rules. Remove .agents/** from additionalIgnores once resolved.

Rollback

Single revert: each phase is a separate commit. Phase 4 (strip Remnant) is the only destructive one, and Phase 2's copies survive. Worst case: git revert <phase-4-commit> restores Remnant, dotfiles copies stay.


WIP: AGENTS.md context survival after compaction

Status: problem noted; solution not designed. Break out into a separate project doc when ready to act on it.

The problem

AGENTS.md loading is a session-start event. Once loaded, the content sits in the context window as a regular document — it does not re-inject. After compaction/summarization, the summary may preserve high-level framing but can silently drop specific rules, enforcement hierarchy details, or lessons added mid-session. The "Lost in the Middle" effect applies even before compaction: guidance in the middle of a long context receives less model attention than content at the tail (hooks inject at the tail specifically to counter this).

The .agents/AGENTS.md enforcement hierarchy already acknowledges this: "Root AGENTS.md sections: Context-start only. Subject to 'lost in the middle.'" The user confirmed this happened: .agents/AGENTS.md was read before compaction this session, but its content was not reliably carried through.

What the research says (verified + falsified + re-corrected May 2026)

VS Code Copilot — correction was itself over-corrected. Final answer:

VS Code docs group copilot-instructions.md, AGENTS.md, and CLAUDE.md as "always-on instructions" injected per-request — but this only applies to files at the workspace root. The docs explicitly note: "Support of AGENTS.md files outside of the workspace root is currently turned off by default."

This session is direct evidence. .agents/AGENTS.md is a subdirectory file, not the workspace-root AGENTS.md. It was read_file'd during this session and entered the context as a regular document. After compaction the summary dropped the specific content — enforcement hierarchy, forbidden patterns. Post-compaction, the Copilot model then proposed .instructions.md files and OpenCode instructions: config — exactly the approaches the forbidden patterns section bans — because that guidance was no longer in the effective context.

Root-level AGENTS.md (workspace root) = always-on, survives compaction.
Nested AGENTS.md in subdirectories = not always-on, read once on explicit read_file, lost on compaction.
The problem is real for both tools for any AGENTS.md that isn't the workspace root file. This repo's enforcement lives in .agents/AGENTS.md, not the workspace root — which means it is compaction-vulnerable in VS Code Copilot too.

OpenCode (opencode.ai/docs/rules + config):

  • AGENTS.md loaded at session start via directory traversal + global ~/.config/opencode/AGENTS.md. No re-injection after compaction is documented. The compaction agent is a hidden system agent; its behavior after summarizing context is not specified. There is no /docs/compaction page — no public spec exists for what happens to AGENTS.md content in the compacted summary.
  • Whether OpenCode re-injects even the root AGENTS.md after compaction is unknown. Needs live testing.

Summary of the asymmetry:

File Copilot VS Code OpenCode
Root AGENTS.md (workspace root) always-on per-request session-start only ⚠️
Nested AGENTS.md (subdirectory) off by default, read-once ⚠️ session-start traversal, read-once ⚠️
Both after compaction root survives; nested lost unknown (undocumented)

Key implication for this repo: the enforcement hierarchy and forbidden patterns live in .agents/AGENTS.md, not the workspace-root AGENTS.md. That makes them compaction-vulnerable in VS Code Copilot. None of the candidate mitigations below have been evaluated yet — this problem is unsolved.

Instruction files vs AGENTS.md (revised):

  • VS Code Copilot: root AGENTS.md and root copilot-instructions.md are both always-on per-request — equivalent. The ban on .instructions.md files is about path-scoping being non-portable, not injection frequency.
  • OpenCode: instructions: config field is session-start — same vulnerability as nested AGENTS.md in OpenCode.

Open questions (narrowed after falsification)

  • Does OpenCode re-inject root AGENTS.md after compaction, or is it also lost? (Needs live testing — not documented.)
  • Does OpenCode's instructions: config field content survive in the compacted summary, or is it lost by the same mechanism?
  • Does Claude Code (invoked directly, not via VS Code) have per-request injection for root AGENTS.md like VS Code Copilot?

Candidate mitigations (not yet chosen)

  1. Extend pre-compact.sh: Before summarization fires, scan the current context for read_file calls on AGENTS.md paths and emit their content into the compaction context so the summary captures them explicitly.

  2. Session-start hook re-read: If session-start.sh can detect it is running post-compaction (e.g. a state file exists from a prior pre-compact.sh run), re-inject the full root AGENTS.md content immediately.

  3. PostToolUse periodic re-injection: The current post-tool-use.sh self-check fires every 15 tool calls. A similar counter could re-inject a condensed version of critical AGENTS.md sections (enforcement hierarchy, forbidden patterns) at the same cadence.

  4. Track and replay: Maintain a list of AGENTS.md files read this session (via PostToolUse file-path check). On pre-compact.sh, emit the paths as a "re-read these after compaction" instruction so the post-compaction agent gets them back.

  5. Stop relying solely on AGENTS.md for critical rules: Move critical, never-forget rules out of AGENTS.md into PreToolUse hard blocks or PostToolUse reminders. Reserve AGENTS.md for architecture/rationale that is worth losing under compaction. This is partly already the design intent — this is a reminder to be strict about it.


Post-Extraction Validation (May 23, 2026)

Validation pass over the extraction work. No code changes made — findings and recommendations only.

Verified working

Dotfiles ~/dotfiles/.agents/ payload is complete:

  • AGENTS.md (289 lines)
  • agents/AGENTS.md, brainstorm.md, build.md, orchestrator.md, research.md
  • skills/research.md
  • hooks/ — all six shared hooks (pre-tool-use, post-tool-use, session-start, stop, pre-compact, user-prompt-submit)
  • mcp/index.ts + package.json + package-lock.json
  • frameworks/opencode/plugin.ts (319 lines, with the Jinja-safe chat.message injection)
  • frameworks/github/hooks.json (full six-hook registration)
  • docs/ — all nine moved docs present (agent-infrastructure.md, ai-coding-best-practices.md, ai_architectures.md, human-llm-interpretation-overlap.md, intent-interpretation-action-plan.md, llm-intent-interpretation.md, text-communication-interpretation.md, text-intent-interpretation-research.md, llama-server-cuda-wsl2.md)
  • install.sh — generates Copilot global hooks JSON with absolute paths, symlinks OpenCode plugin + agents + global AGENTS.md, merges OpenCode and VS Code MCP entries, installs MCP server deps

Global wiring on this machine is live:

  • ~/.copilot/hooks/agent-support.json — generated, absolute paths
  • ~/.config/opencode/AGENTS.md~/dotfiles/.agents/AGENTS.md
  • ~/.config/opencode/plugins/agent-support.ts~/dotfiles/.agents/frameworks/opencode/plugin.ts
  • ~/.config/opencode/agents/{brainstorm,build,orchestrator,research}.md symlinks
  • ~/.config/opencode/opencode.json — has all-agents MCP entry
  • ~/.vscode-server/data/User/mcp.json — has both all-agents and exa
  • ~/.vscode-server/data/User/prompts/ — exists (empty)

Remnant overlay is correctly scoped:

  • .agents/AGENTS.md (Remnant-specific)
  • .agents/README.md
  • .agents/hooks/post-tool-use-remnant.sh (BFF only)
  • .agents/frameworks/github/{AGENTS.md, hooks.json} — project Copilot hook registration
  • .agents/frameworks/opencode/{AGENTS.md, hooks.ts} — project OpenCode plugin
  • .github/hooks/hooks.json../../.agents/frameworks/github/hooks.json
  • .opencode/plugins/hooks.ts../../.agents/frameworks/opencode/hooks.ts
  • .opencode/AGENTS.md warning file

⚠️ Gaps and bugs in dotfiles (pre-push)

These should be fixed before squashing/pushing the dotfiles commits.

  1. ~/dotfiles/.agents/AGENTS.md references stale paths from the pre-extraction layout. Three places reference .agents/github/ and .agents/opencode/ but the canonical paths are now .agents/frameworks/github/ and .agents/frameworks/opencode/:

    • "The Copilot harness (.agents/github/hooks.json) and OpenCode plugin (.agents/opencode/plugin.ts) both delegate…" (Hook Files section)
    • ".agents/opencode/plugin.ts — OpenCode plugin harness (canonical)" (Tool-Specific Entry Points section)
    • ".agents/github/hooks.json — Copilot harness config (canonical)" (same section)
    • Also: the surrounding sentences claim symlinks point from .github/hooks/agent-support.json and .opencode/plugins/agent-support.ts "those directories are gitignored." In dotfiles this is wrong on two counts: (a) global wiring uses ~/.copilot/hooks/agent-support.json and ~/.config/opencode/plugins/agent-support.ts, (b) at Remnant the project symlink files are named hooks.json and hooks.ts, not agent-support.*. The doc was written for the pre-split layout and never updated.
  2. ~/dotfiles/.agents/AGENTS.md links into ../docs/research/... — Remnant-relative paths that don't resolve in dotfiles. Two link targets:

    • [docs/research/intent-interpretation-action-plan.md](../docs/research/intent-interpretation-action-plan.md)
    • [docs/research/ai-coding-best-practices.md](../docs/research/ai-coding-best-practices.md) Should be ./docs/intent-interpretation-action-plan.md and ./docs/ai-coding-best-practices.md (the docs moved into .agents/docs/, not docs/research/).
  3. No "Research Discipline" section in ~/dotfiles/.agents/AGENTS.md. Plan Phase 2 step 1 specifically called for adding one (replacing the Copilot-only memory at ~/memories/research-discipline.md). The Copilot memory still exists as a stopgap because the dotfiles AGENTS.md doesn't carry the equivalent guidance.

  4. frameworks/github/AGENTS.md and frameworks/opencode/AGENTS.md are missing from dotfiles. Remnant added rich, generic API-facts AGENTS.md files for each framework dir (62ee78c) — the content is not Remnant-specific (verified VS Code hooks output formats, OpenCode plugin API facts, Jinja constraint, overconfidence warnings). These belong in dotfiles alongside the framework configs; right now an agent editing the global frameworks/opencode/plugin.ts won't see them.

  5. install.sh location. Currently ~/dotfiles/.agents/install.sh. Recommendation: move to ~/dotfiles/install.sh so the dotfiles repo has a discoverable bootstrap entry point (and to leave room for installing other dotfiles content beyond .agents/). The script uses DOTFILES_AGENTS="$(cd "$(dirname "$0")" && pwd)" — moving it requires changing that one line to e.g. DOTFILES_AGENTS="$(cd "$(dirname "$0")" && pwd)/.agents". No other path math in the script needs to change.

  6. install.sh does not symlink anything into ~/.copilot/ beyond hooks/. Copilot also supports user-level inline settings at ~/.copilot/settings.json. Not required, just noting it's a future extension point if more global Copilot config becomes shareable.

  7. install.sh doesn't create the ~/.vscode-server/data/User/prompts/ dir as part of the run on this machine — directory exists but is empty. Confirmed step 6 ran (mkdir -p). Working as intended; the dir is the surface for VS Code prompt files but none have been authored yet. No action needed unless we plan to ship .prompt.md files from dotfiles.

  8. install.sh has no uninstall counterpart. Low-priority. Useful if we start moving the script around and want clean state for testing.

  9. Exa MCP has an undocumented rate limit; agents fan out parallel mcp_exa_web_search_exa calls and hit it. Observed May 23, 2026: 8 parallel searches in one turn → all cancelled. Two complementary fixes, both in dotfiles:

    • PostToolUse nudge in ~/dotfiles/.agents/hooks/post-tool-use.sh: after any mcp_exa_* call, inject a reminder ("Exa rate-limits parallel calls — issue web searches serially, max ~2 per turn") so the model learns the pattern without a hard block.
    • AGENTS.md entry under a new "External service quirks" section listing per-service constraints (Exa rate limit, GitHub API limits when mcp_github_* lands, etc.). Loaded at session start so the model has it before issuing the first call.
    • Optional PreToolUse soft-warn: count mcp_exa_* calls per turn via a /tmp/.exa-turn-count file (reset on user-prompt-submit); warn (don't deny) past N=2.

🧹 Commit-history cleanup recommendations

Sonnet committed in tiny increments. Both repos have a series of unpushed "fix(install)/fix(plugin)/fix(hooks)" commits that should be squashed before publishing.

~/dotfiles — 10 unpushed commits on main past 4a44460 (origin/main). Suggested single squashed commit:

feat(.agents): shared agent infrastructure + install.sh

- Hooks, agents, skills, MCP server, OpenCode plugin, Copilot hook config
- install.sh wires global Copilot hooks (absolute paths), OpenCode plugin
  + agents + AGENTS.md (symlinks), MCP entries for OpenCode and VS Code
- See .agents/docs/agent-infrastructure.md for design rationale

Constituent commits to fold in: 6b07e4c 690178d 88435d6 f4017ab 5c12257 f0d21e9 2949981 3738732 9544b4e 14c132a.

Suggested workflow: git reset --soft 4a44460 && git commit -m '…' (or interactive rebase with s on every commit after the first). Address items 14 above first so the squash captures clean state.

~/code/remnant — many unpushed commits past 0d0a3a8 (origin/main); the agent-infra-related ones form a contiguous block from 2d58147 through 78c8449. Suggested squash boundary:

  • Keep 2d58147 as the first commit of the block, or replace it with a new "feat: extract shared agent infra to ~/dotfiles/.agents" message that covers the full final state.
  • Fold in: 5a7d220 c41c142 daf53a3 8a61128 2b0ea1e e9f3529 9191a44 fc2a944 62ee78c dc3ec9c 78c8449.

The non-agent-infra commits before 2d58147 (the older "chore: more agentic coding updates …" block) are pre-extraction and can be left as-is or squashed separately depending on taste.

📋 Pending work that's still extraction-scoped

  • MODELFILES.md stub (Phase 4 item 3) — explicitly skipped; consider whether the two omnicoder*.modelfile files in Remnant should be moved to ~/dotfiles/.agents/modelfiles/ and dropped from Remnant entirely. They aren't Remnant-specific.
  • .agents/ TypeScript ESLint conformance (Out-of-scope list, item 4) — still tracked; no movement.
  • Item 22 in agent-infrastructure.md (platform-agnostic hook scripts) — unchanged.
  • Live-session smoke tests from Phase 5 (slash commands, BFF reminder injection, VS Code MCP all-agents connect) — still marked . Should be retired or confirmed after the next session restart.

🚀 Starting a new project on the extracted infra (MFE)

Moved to dotfiles-agent-infra-roadmap.md. The short version:

  • Inheriting the global infra is automatic once install.sh has run on the machine — no per-project setup beyond an AGENTS.md and (optionally) an overlay hook.
  • The blocker for full MFE adoption is that stop.sh hardcodes Remnant's task layout (docs/TODO.md, docs/projects/COMPLETED.md, docs/explorations/). This is part of the hook audit below and is addressed by the project.config.js extraction tracked in the roadmap.

🆕 Future task — unify kanban/task doc structure across projects

Moved to dotfiles-agent-infra-roadmap.md → Kanban / task-doc unification. Driver recorded here for context: stop.sh hardcodes Remnant's task layout, and the path forward (after project.config.js lands) is for the hook to support multiple shapes driven by config rather than a single hardcoded one.

🔎 Full hook-script Remnant-isms audit (May 23, 2026 — addendum)

Re-read every hook in ~/dotfiles/.agents/hooks/ line-by-line after the stop.sh miss. Findings below — anything not listed is reviewed and verified generic.

pre-tool-use.sh — multiple hardcodes that bite non-Remnant projects:

  1. Policy 5 — hardcoded ports 3000/3001 for dev-server detection:

    ss -tlnp 2>/dev/null | grep -qE ':300[01]\s'
    

    These are Remnant's apps/api (3000) and apps/client Vite HMR (3001). MFE uses different ports (likely 5173 for Vite, plus app-specific). Fix: read ports from a per-project config (.agents/project.json with a devPorts array) or from package.json script scraping, default to common ports if unset.

  2. Policy 8 — error message references npm run build:core (Remnant has a packages/core package that owns the codegen step; other projects don't):

    "Edit the source files (controller.ts, routes.ts, business-logic.ts) instead and run 'npm run build:core' to regenerate." The .generated.ts block itself is generic, but the message and example filenames are Remnant-specific. Fix: parameterize the rebuild command via project config, or genericize the message ("run the generator script for the affected package").

  3. Policies 9 & 10 — assume wireit is the build tool. Both error messages reference wireit cache/fingerprint behavior and tell the agent to edit wireit config in package.json. Remnant uses wireit; MFE may not. The blocks themselves (rm .wireit, -- --force with npm run) are still useful — they fire on the literal string .wireit and the --force flag — but the messages will be confusing for non-wireit projects. Fix: detect wireit presence (grep -q '"wireit"' package.json) and skip the block when not present, or rewrite messages to be tool-agnostic.

  4. Policy 11 — assumes npm workspaces (npm run format -- <file> propagation issue). True for any npm-workspaces monorepo; false for single-package projects (where the arg works fine). Low-impact: even in a single-package repo, the block just prevents a working command. Fix: gate on presence of workspaces field in root package.json.

  5. Policy 14 — hardcoded apps/*/package.json and packages/*/package.json paths. This is the exact Remnant monorepo layout (apps/api, apps/client, packages/core, etc.). MFE may use apps/ + packages/ too but the underlying concern — that reading workspace package.json files auto-injects nested AGENTS.md and exhausts context — applies to any monorepo with nested AGENTS.md files, regardless of directory names. Also: the message hardcodes "32K context window", which is a specific assumption about the local model (qwen3-coder-30b on llama-server). Cloud models have 200K+. Fix: discover workspace dirs from package.json workspaces field; drop the model-size number or make it configurable.

post-tool-use.sh — mostly generic, one cosmetic issue:

  1. vscode_renameSymbol reminder uses Remnant-flavored example strings: deleteX: archiveX, openDialog('delete-item'), AppDialog handle='delete-item', deleteSuccess/Loading/Error. These are illustrative patterns from Remnant's Solid.js store + AppDialog component. They're not incorrect for other projects, just visibly Remnant-coded. Low-priority: either genericize ("e.g. aliased store keys like oldName: newName in a returned object") or leave as concrete examples — they still teach the right habit. The header comment correctly notes that project-specific reminders "belong in a sibling project-local hook file," but this one snuck in.

  2. opencode agent list shell-out assumes OpenCode CLI is installed. Fires only when editing agent definitions, so the blast radius is small (a Copilot user who never edits agents won't see it). The fallback ("opencode agent list failed") is graceful. Acceptable as-is, but worth noting: Copilot-only environments will hit the failure path every time. Could gate on command -v opencode.

pre-compact.sh:

  1. docs/explorations/ hardcoded (same path issue as stop.sh). Already covered by the kanban-unification task above — fold into that work.

session-start.sh:

  1. docs/explorations/ hardcoded (same — fold into kanban-unification).

  2. .session/dead-ends.md and .session/pre-compact-state.md paths appear in both session-start.sh, pre-compact.sh, and stop.sh. This is a convention .agents/AGENTS.md should formally document so it's not just "magic paths the hooks know about." Not Remnant-specific (no Remnant code references these), but undocumented. Fix: add a "Session conventions" section to ~/dotfiles/.agents/AGENTS.md listing these paths.

  3. "Ordered markdown lists are auto-renumbered by the editor on save" reminder — this is VS Code + Prettier behavior, generic enough to keep, but worth flagging that it assumes the project uses Prettier with that setting (Remnant does; others may not).

stop.sh (already covered, restated for completeness):

  1. docs/TODO.md, docs/projects/COMPLETED.md, docs/explorations/ — kanban task.

  2. Ports 3000/3001 dev-server check (same as Policy 5 — fold fix together).

  3. npm run build:strict referenced as the recommended verification command. This is a Remnant-specific custom script name. Other projects use npm run build or npm run check or npm run ci. Fix: same parameterize approach (read from .agents/project.json).

user-prompt-submit.sh: clean. No Remnant-isms found.

Suggested fix pattern (rather than a string of patches):

Introduce a per-project config file at <repo>/.agents/project.config.js (or .ts) so each hook can read its values instead of hardcoding them. Full design — file shape, loader notes, dropped fields (modelContextWindow), recommendation — is in dotfiles-agent-infra-roadmap.md → project.config.js extraction.

🆕 Future task — per-session tmp file capture

Moved to dotfiles-agent-infra-roadmap.md → Per-session tmp file capture. Driver recorded here for the validation trail: user-prompt-submit.sh writes to a globally-named /tmp/.last-user-prompt.txt, so concurrent sessions clobber one another's capture. The same issue affects /tmp/.opencode-tool-count-${REPO_ID} in post-tool-use.sh (keyed by repo, not session — concurrent sessions in the same repo share the self-check counter).