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

772 lines
39 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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](./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-agents``all-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](https://docs.github.com/en/copilot/reference/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-agents``all-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-agents``all-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](./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](#-full-hook-script-remnant-isms-audit-may-23-2026--addendum)
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](./dotfiles-agent-infra-roadmap.md#4-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:
```bash
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:**
6. **`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.
7. **`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`:**
8. **`docs/explorations/` hardcoded** (same path issue as `stop.sh`). Already
covered by the kanban-unification task above — fold into that work.
**`session-start.sh`:**
9. **`docs/explorations/` hardcoded** (same — fold into kanban-unification).
10. **`.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.
11. **"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):**
12. `docs/TODO.md`, `docs/projects/COMPLETED.md`, `docs/explorations/` — kanban
task.
13. **Ports 3000/3001** dev-server check (same as Policy 5 — fold fix together).
14. **`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](./dotfiles-agent-infra-roadmap.md#1-projectconfigjs-extraction).
### 🆕 Future task — per-session tmp file capture
Moved to
[dotfiles-agent-infra-roadmap.md → Per-session tmp file capture](./dotfiles-agent-infra-roadmap.md#2-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).