-
-```
-
-### Hand-built boxes-and-arrows (when Mermaid's layout fights you)
-
-Modules as `- flowchart LR - A[OrderHandler] --> B[OrderValidator] - B --> C[OrderRepo] - C -.leak.-> D[PricingClient] - classDef leak stroke:#dc2626,stroke-width:2px; - class C,D leak --
`s with borders and labels. Arrows as inline SVG `` or `` elements positioned absolutely over a relative container. Reach for this when you want the "after" diagram to feel like one thick-bordered deep module with greyed-out internals — Mermaid won't render that with the right weight.
-
-### Cross-section (good for layered shallowness)
-
-Stack horizontal bands (`h-12 border-l-4`) to show layers a call passes through. Before: 6 thin layers each doing nothing. After: 1 thick band labelled with the consolidated responsibility.
-
-### Mass diagram (good for "interface as wide as implementation")
-
-Two rectangles per module — one for interface surface area, one for implementation. Before: interface rectangle is nearly as tall as the implementation rectangle (shallow). After: interface rectangle is short, implementation rectangle is tall (deep).
-
-### Call-graph collapse
-
-Before: a tree of function calls rendered as nested boxes. After: the same tree collapsed into one box, with the now-internal calls shown faded inside it.
-
-## Style guidance
-
-- Lean editorial, not corporate-dashboard. Generous whitespace. Serif optional for headings (`font-serif` works well with stone/slate).
-- Colour sparingly: one accent (emerald or indigo) plus red for leakage and amber for warnings.
-- Keep diagrams ~320px tall so before/after sits comfortably side by side without scrolling.
-- Use `text-xs uppercase tracking-wider` for module labels inside diagrams — they should read as schematic, not as UI.
-- The only scripts are the Tailwind CDN and the Mermaid ESM import. The report is otherwise static — no app code, no interactivity beyond Mermaid's own rendering.
-
-## Top recommendation section
-
-One larger card. Candidate name, one sentence on why, anchor link to its card. That's it.
+End with the recommended next step and its reason. The report does not authorize implementation.
## Tone
-Plain English, concise — but the architectural nouns and verbs come straight from the `/codebase-design` skill. Concision is not an excuse to drift.
+Use concise, evidence-backed explanations. Preserve project vocabulary and describe the relevant design concept where useful.
-**Use exactly:** module, interface, implementation, depth, deep, shallow, seam, adapter, leverage, locality.
+Terms such as module, interface, depth, seam, leverage, and locality can clarify the design.
-**Never substitute:** component, service, unit (for module) · API, signature (for interface) · boundary (for seam) · layer, wrapper (for module, when you mean module).
+Names such as component, service, API, boundary, layer, or wrapper are appropriate when they accurately name the project element. Do not replace established terms just to satisfy a glossary.
**Phrasings that fit the style:**
- "Order intake module is shallow — interface nearly matches the implementation."
- "Pricing leaks across the seam."
- "Deepen: one interface, one place to test."
-- "Two adapters justify the seam: HTTP in prod, in-memory in tests."
+- "The payment boundary isolates network failures in tests."
-**Wins bullets** name the gain in glossary terms: *"locality: bugs concentrate in one module"*, *"leverage: one interface, N call sites"*, *"interface shrinks; implementation absorbs the wrappers"*. Don't write *"easier to maintain"* or *"cleaner code"* — those terms aren't in the glossary and don't earn their place.
+Describe concrete gains such as fewer caller obligations or preserved coverage through one contract. Avoid unsupported claims of cleaner code, regardless of vocabulary.
-No hedging, no throat-clearing, no "it's worth noting that…". If a sentence could be a bullet, make it a bullet. If a bullet could be cut, cut it. If a term isn't in the `/codebase-design` glossary, reach for one that is before inventing a new one.
+State uncertainty and trade-offs honestly. Use only the formatting needed to make the finding understandable.
diff --git a/.agents/skills/improve-codebase-architecture/SKILL.md b/.agents/skills/improve-codebase-architecture/SKILL.md
index 529761a..962758a 100644
--- a/.agents/skills/improve-codebase-architecture/SKILL.md
+++ b/.agents/skills/improve-codebase-architecture/SKILL.md
@@ -1,7 +1,6 @@
---
name: improve-codebase-architecture
-description: Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.
-disable-model-invocation: true
+description: Review a codebase for module-deepening opportunities and explain the most useful candidates. Use for an architecture survey or a specified area of architectural friction.
---
# Improve Codebase Architecture
@@ -10,7 +9,7 @@ Surface architectural friction and propose **deepening opportunities** — refac
This command is _informed_ by the project's domain model and built on a shared design vocabulary:
-- Run the `/codebase-design` skill for the architecture vocabulary (**module**, **interface**, **depth**, **seam**, **adapter**, **leverage**, **locality**) and its principles (the deletion test, "the interface is the test surface", "one adapter = hypothetical seam, two = real"). Use these terms exactly in every suggestion — don't drift into "component," "service," "API," or "boundary."
+- Use `/codebase-design` to reason about module depth, caller contracts, locality, and justified test seams. Preserve project names such as component, service, or API; explain concepts without imposing a competing vocabulary or adapter count.
- The domain language in `CONTEXT.md` gives names to good seams; ADRs in `docs/adr/` record decisions this command should not re-litigate.
## Process
@@ -24,7 +23,7 @@ This command is _informed_ by the project's domain model and built on a shared d
Read the project's domain glossary (`CONTEXT.md`) and any ADRs in the area you're touching first.
-Then spawn a sub-agent to walk the codebase. Don't follow rigid heuristics — explore organically and note where you experience friction:
+Explore directly or delegate bounded independent areas through the available tools when useful. Note concrete friction:
- Where does understanding one concept require bouncing between many small modules?
- Where are modules **shallow** — interface nearly as complex as the implementation?
@@ -34,11 +33,11 @@ Then spawn a sub-agent to walk the codebase. Don't follow rigid heuristics — e
Apply the **deletion test** to anything you suspect is shallow: would deleting it concentrate complexity, or just move it? A "yes, concentrates" is the signal you want.
-### 2. Present candidates as an HTML report
+### 2. Present the useful candidates
-Write a self-contained HTML file to the OS temp directory so nothing lands in the repo. Resolve the temp dir from `$TMPDIR`, falling back to `/tmp` (or `%TEMP%` on Windows), and write to `/architecture-review-.html` so each run gets a fresh file. Open it for the user — `xdg-open ` on Linux, `open ` on macOS, `start ` on Windows — and tell them the absolute path.
+Honor the requested format and output path. A concise Markdown report is enough for a few findings. For a requested visual HTML report, use a fresh temporary path by default and provide its location; open it only when requested.
-The report uses **Tailwind via CDN** for layout and styling, and **Mermaid via CDN** for diagrams where a graph/flow/sequence reliably communicates the structure. Mix Mermaid with hand-crafted CSS/SVG visuals — use Mermaid when relationships are graph-shaped (call graphs, dependencies, sequences), and hand-built divs/SVG when you want something more editorial (mass diagrams, cross-sections, collapse animations). Each candidate gets a **before/after visualisation**. Be visual.
+Use a diagram only when relationships or a before/after change are clearer visually. Prefer static HTML/CSS/SVG or existing renderers; do not add CDN scripts or dependencies for a simple report.
For each candidate, render a card with:
@@ -46,24 +45,24 @@ For each candidate, render a card with:
- **Problem** — why the current architecture is causing friction
- **Solution** — plain English description of what would change
- **Benefits** — explained in terms of locality and leverage, and how tests would improve
-- **Before / After diagram** — side-by-side, custom-drawn, illustrating the shallowness and the deepening
+- **Before / After diagram** — only when it materially clarifies the change
- **Recommendation strength** — one of `Strong`, `Worth exploring`, `Speculative`, rendered as a badge
End the report with a **Top recommendation** section: which candidate you'd tackle first and why.
-**Use CONTEXT.md vocabulary for the domain, and the `/codebase-design` vocabulary for the architecture.** If `CONTEXT.md` defines "Order," talk about "the Order intake module" — not "the FooBarHandler," and not "the Order service."
+Use `CONTEXT.md` vocabulary for the domain and accurate project names for the implementation. Design terms should clarify the proposed change, not rename existing concepts without need.
**ADR conflicts**: if a candidate contradicts an existing ADR, only surface it when the friction is real enough to warrant revisiting the ADR. Mark it clearly in the card (e.g. a warning callout: _"contradicts ADR-0007 — but worth reopening because…"_). Don't list every theoretical refactor an ADR forbids.
-See [HTML-REPORT.md](HTML-REPORT.md) for the full HTML scaffold, diagram patterns, and styling guidance.
+For HTML output, read [HTML-REPORT.md](HTML-REPORT.md) for a small offline scaffold and relevant diagram options.
-Do NOT propose interfaces yet. After the file is written, ask the user: "Which of these would you like to explore?"
+Return the requested survey with a recommendation. If the user wants an interactive design session, offer to explore a candidate; otherwise stop at the report.
### 3. Grilling loop
-Once the user picks a candidate, run the `/grilling` skill to walk the decision tree with them — constraints, dependencies, the shape of the deepened module, what sits behind the seam, what tests survive.
+When the user requests an interview about a candidate, use `/grilling` for unresolved constraints and decisions. Reuse existing answers and honor a request for a direct design recommendation instead.
-Side effects happen inline as decisions crystallize — run the `/domain-modeling` skill to keep the domain model current as you go:
+When domain-document updates are within scope, use `/domain-modeling` as decisions crystallize; a read-only architecture report should only recommend these updates:
- **Naming a deepened module after a concept not in `CONTEXT.md`?** Add the term to `CONTEXT.md`. Create the file lazily if it doesn't exist.
- **Sharpening a fuzzy term during the conversation?** Update `CONTEXT.md` right there.
diff --git a/.agents/skills/loop-me/SKILL.md b/.agents/skills/loop-me/SKILL.md
new file mode 100644
index 0000000..3dc6261
--- /dev/null
+++ b/.agents/skills/loop-me/SKILL.md
@@ -0,0 +1,30 @@
+---
+name: loop-me
+description: Grill me about specs for the workflows I want to build, within this workspace.
+---
+
+Run a stateful `/grilling` session whose output is **workflow** specs. Use one question at a time with a recommendation, focused on the requested workflow. Update relevant specs as decisions resolve; preserve unrelated specs and remove an existing one only when the user has authorized that scope change.
+
+## The loop lens
+
+A **loop** is a recurring pattern in the user's life: their career, their week, their morning, a single repeated activity. Picturing a life as loops within loops reveals how predictable its activities really are — which is what makes them worth **delegating**. Use the lens to find loops worth specifying, and propose ones the user hasn't noticed.
+
+A **workflow** is the spec of one loop, made real. You run a workflow on a loop — the loop is its running instantiation. Workflows live in `workflows/*.md` and are the source of truth.
+
+## Vocabulary
+
+A shared language, reached for only when a workflow calls for it — never a checklist. **Mandate nothing structural**: a workflow needs no AI, no checkpoint, and no schedule unless the grilling shows it does.
+
+- **Trigger** — what fires each run: an **event** (a new email, a new issue) or a **schedule** (every morning). Event-triggering is usually the more efficient.
+- **Checkpoint** — a human-in-the-loop point where the user is asked to verify or decide. Some workflows have none and run autonomously; some use no AI at all.
+- **Push right** — defer the checkpoint as far as it will go. Do maximal work before involving the human, so they are asked once, late, with everything prepared.
+- **Brief** — what a checkpoint presents: a tight, decision-ready summary — what was produced, why, and a link down to the asset itself — never the raw output. The user reads a brief, not a draft. Speed of review is imperative.
+
+## Definition of done
+
+A workflow spec is done when its scope, inputs, outputs, authority, failure handling, and acceptance criteria are actionable. Record safe assumptions and optional future questions; keep interviewing only about decisions that materially affect the requested workflow.
+
+## The workspace
+
+- `workflows/*.md` — one spec per workflow.
+- `NOTES.md` — relevant tools, channels, preferences, and terminology already learned. Missing notes do not block a clear request; ask only for context needed by this workflow and avoid collecting unrelated personal details.
diff --git a/.agents/skills/loop-me/agents/openai.yaml b/.agents/skills/loop-me/agents/openai.yaml
new file mode 100644
index 0000000..1a4f411
--- /dev/null
+++ b/.agents/skills/loop-me/agents/openai.yaml
@@ -0,0 +1,5 @@
+interface:
+ display_name: "Loop Me"
+ short_description: "Spec the workflows you want to build"
+policy:
+ allow_implicit_invocation: false
diff --git a/.agents/skills/luna-verified-implement/SKILL.md b/.agents/skills/luna-verified-implement/SKILL.md
new file mode 100644
index 0000000..fc76659
--- /dev/null
+++ b/.agents/skills/luna-verified-implement/SKILL.md
@@ -0,0 +1,24 @@
+---
+name: luna-verified-implement
+description: Implement a spec or ticket with gpt-6-luna implementation subagents and independently verify the final change with the orchestrator's model and reasoning effort. Use when the user asks to implement, build, or fix work and wants delegated implementation with a verification pass.
+---
+
+# Luna Verified Implement
+
+Invoke `$implement` and follow it as the baseline workflow. Treat this skill as its delegated, verified variant.
+
+## Workflow
+
+1. Read the spec or ticket, repository guidance, affected flow, and existing worktree changes. Record the starting commit and task-owned scope; preserve unrelated changes.
+2. Split only genuinely independent, bounded work. If the change is small or one seam owns it, use one implementation agent; do not manufacture parallelism.
+3. Spawn each implementation agent with `fork_turns: "none"`, `model: "gpt-6-luna"`, and `reasoning_effort: "max"`. Give each its exact owned files/seam, acceptance criteria, required checks, and task-local context. Tell agents not to overwrite or revert other agents' work.
+4. Wait for agents, inspect their diffs, resolve overlaps minimally, and run the implementation checks required by `$implement`: targeted tests and typecheck during work, then the full relevant suite once.
+5. Spawn a fresh, read-only verification agent with `fork_turns: "none"`, `model` and `reasoning_effort` set to the orchestrator's current values. Do not hard-code a different model or reasoning effort for verification. Give it the original request, current diff, and test output, but not implementation conclusions. Ask it to check correctness, regressions, specification coverage, and test evidence. Have it report findings without changing files.
+6. Fix confirmed findings, rerun affected checks, and repeat verification once if fixes were needed. Run `$code-review` on the current working result (including staged, unstaged, and new files), passing the original spec, starting commit, and task-owned scope. Follow `$implement`'s commit boundary: commit only when requested, otherwise hand off the verified diff.
+
+## Delegation rules
+
+- Keep all agents in the same workspace; assign non-overlapping ownership before they edit.
+- Use at most the available concurrency slots. Reserve one slot for coordination and verification.
+- Do not delegate secrets, production writes, destructive operations, or changes requiring new user authority.
+- If subagents are unavailable, implement directly, run the same checks, and state that delegated verification was unavailable.
diff --git a/.agents/skills/luna-verified-implement/agents/openai.yaml b/.agents/skills/luna-verified-implement/agents/openai.yaml
new file mode 100644
index 0000000..d17ca17
--- /dev/null
+++ b/.agents/skills/luna-verified-implement/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Luna Verified Implement"
+ short_description: "Delegate implementation and verify it"
+ default_prompt: "Use $luna-verified-implement to implement this task with Luna agents and verify the result."
diff --git a/.agents/skills/migrate-to-shoehorn/SKILL.md b/.agents/skills/migrate-to-shoehorn/SKILL.md
new file mode 100644
index 0000000..ae4f965
--- /dev/null
+++ b/.agents/skills/migrate-to-shoehorn/SKILL.md
@@ -0,0 +1,118 @@
+---
+name: migrate-to-shoehorn
+description: Migrate test files from `as` type assertions to @total-typescript/shoehorn. Use when user mentions shoehorn, wants to replace `as` in tests, or needs partial test data.
+---
+
+# Migrate to Shoehorn
+
+## Why shoehorn?
+
+`shoehorn` lets you pass partial data in tests while keeping TypeScript happy. It replaces `as` assertions with type-safe alternatives.
+
+**Test code only.** Never use shoehorn in production code.
+
+Problems with `as` in tests:
+
+- Trained not to use it
+- Must manually specify target type
+- Double-as (`as unknown as Type`) for intentionally wrong data
+
+## Install
+
+```bash
+npm i @total-typescript/shoehorn
+```
+
+## Migration patterns
+
+### Large objects with few needed properties
+
+Before:
+
+```ts
+type Request = {
+ body: { id: string };
+ headers: Record;
+ cookies: Record;
+ // ...20 more properties
+};
+
+it("gets user by id", () => {
+ // Only care about body.id but must fake entire Request
+ getUser({
+ body: { id: "123" },
+ headers: {},
+ cookies: {},
+ // ...fake all 20 properties
+ });
+});
+```
+
+After:
+
+```ts
+import { fromPartial } from "@total-typescript/shoehorn";
+
+it("gets user by id", () => {
+ getUser(
+ fromPartial({
+ body: { id: "123" },
+ }),
+ );
+});
+```
+
+### `as Type` → `fromPartial()`
+
+Before:
+
+```ts
+getUser({ body: { id: "123" } } as Request);
+```
+
+After:
+
+```ts
+import { fromPartial } from "@total-typescript/shoehorn";
+
+getUser(fromPartial({ body: { id: "123" } }));
+```
+
+### `as unknown as Type` → `fromAny()`
+
+Before:
+
+```ts
+getUser({ body: { id: 123 } } as unknown as Request); // wrong type on purpose
+```
+
+After:
+
+```ts
+import { fromAny } from "@total-typescript/shoehorn";
+
+getUser(fromAny({ body: { id: 123 } }));
+```
+
+## When to use each
+
+| Function | Use case |
+| --------------- | -------------------------------------------------- |
+| `fromPartial()` | Pass partial data that still type-checks |
+| `fromAny()` | Pass intentionally wrong data (keeps autocomplete) |
+| `fromExact()` | Force full object (swap with fromPartial later) |
+
+## Workflow
+
+1. **Gather requirements** - ask user:
+ - What test files have `as` assertions causing problems?
+ - Are they dealing with large objects where only some properties matter?
+ - Do they need to pass intentionally wrong data for error testing?
+
+2. **Install and migrate**:
+ - [ ] Install: `npm i @total-typescript/shoehorn`
+ - [ ] Find test files with `as` assertions: `grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts"`
+ - [ ] Replace `as Type` with `fromPartial()`
+ - [ ] Replace `as unknown as Type` with `fromAny()`
+ - [ ] Add imports from `@total-typescript/shoehorn`
+ - [ ] Run type check to verify
diff --git a/.agents/skills/migrate-to-shoehorn/agents/openai.yaml b/.agents/skills/migrate-to-shoehorn/agents/openai.yaml
new file mode 100644
index 0000000..3bd79ee
--- /dev/null
+++ b/.agents/skills/migrate-to-shoehorn/agents/openai.yaml
@@ -0,0 +1,3 @@
+interface:
+ display_name: "Migrate to Shoehorn"
+ short_description: "Replace test assertions with shoehorn"
diff --git a/.agents/skills/obsidian-vault/SKILL.md b/.agents/skills/obsidian-vault/SKILL.md
new file mode 100644
index 0000000..9f867c4
--- /dev/null
+++ b/.agents/skills/obsidian-vault/SKILL.md
@@ -0,0 +1,16 @@
+---
+name: obsidian-vault
+description: Search, create, and manage notes in the Obsidian vault with wikilinks and index notes. Use when user wants to find, create, or organize notes in Obsidian.
+---
+
+# Obsidian Vault
+
+Resolve the vault from the user's selected path, workspace configuration, or available Obsidian connection. If several vaults are plausible or none is configured, ask which one to use. Verify access before searching or writing; do not assume a personal machine path.
+
+Read the selected vault's instructions and nearby notes. Preserve its folder layout, naming, frontmatter, and index conventions instead of imposing a flat structure or title-case names.
+
+- Search filenames with `rg --files ` and content with `rg`, scoped to the selected vault.
+- Use existing `[[wikilinks]]` conventions; check the destination note before adding a link.
+- For a new note, search for existing coverage first, then add only relevant links and index entries.
+- Before moving or renaming a note, check backlinks and update affected links within the requested scope.
+- For read-only questions, return the relevant notes without reorganizing the vault.
diff --git a/.agents/skills/obsidian-vault/agents/openai.yaml b/.agents/skills/obsidian-vault/agents/openai.yaml
new file mode 100644
index 0000000..cb70f99
--- /dev/null
+++ b/.agents/skills/obsidian-vault/agents/openai.yaml
@@ -0,0 +1,3 @@
+interface:
+ display_name: "Obsidian Vault"
+ short_description: "Manage linked notes in Obsidian"
diff --git a/.agents/skills/prototype/LOGIC.md b/.agents/skills/prototype/LOGIC.md
index 5f5a3fd..292e624 100644
--- a/.agents/skills/prototype/LOGIC.md
+++ b/.agents/skills/prototype/LOGIC.md
@@ -1,15 +1,13 @@
# Logic Prototype
-A single, self-contained HTML file — a **shareable demo** — that lets anyone drive a state model by clicking buttons. Use this when the question is about **business logic, state transitions, or data shape** — the kind of thing that looks reasonable on paper but only feels wrong once you push it through real cases.
-
-Because it's one file with nothing to install, you can hand it to a non-developer — a designer, a PM, a domain expert — and let them feel the model for themselves. So it speaks their language, not the code's.
+A tiny interactive terminal app that lets the user drive a state model by hand. Use this when the question is about **business logic, state transitions, or data shape** — the kind of thing that looks reasonable on paper but only feels wrong once you push it through real cases.
## When this is the right shape
- "I'm not sure if this state machine handles the edge case where X then Y."
- "Does this data model actually let me represent the case where..."
- "I want to feel out what the API should look like before writing it."
-- Anything where someone wants to **press buttons and watch state change**.
+- Anything where the user wants to **press buttons and watch state change**.
If the question is "what should this look like" — wrong branch. Use [UI.md](UI.md).
@@ -17,11 +15,17 @@ If the question is "what should this look like" — wrong branch. Use [UI.md](UI
### 1. State the question
-Before writing code, write down what state model and what question you're prototyping. One paragraph, at the top of the demo (in a visible intro, not just a comment). A logic prototype that answers the wrong question is pure waste — make the question explicit so it can be checked later, whether the user is watching now or returning to it AFK.
+Before writing code, write down what state model and what question you're prototyping. One paragraph, in the prototype's README or a comment at the top of the file. A logic prototype that answers the wrong question is pure waste — make the question explicit so it can be checked later, whether the user is watching now or returning to it AFK.
-### 2. Isolate the logic in a portable module
+### 2. Pick the language
-Put the actual logic — the bit that's answering the question — in a single `