|
| 1 | +--- |
| 2 | +title: "/archcore:context — Filtering Pipeline" |
| 3 | +status: accepted |
| 4 | +tags: |
| 5 | + - "commands" |
| 6 | + - "plugin" |
| 7 | + - "skills" |
| 8 | +--- |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +This document describes which documents `/archcore:context` surfaces and which it drops, across the two layers of the pipeline. Use it as a lookup when: |
| 13 | + |
| 14 | +- a relevant document doesn't appear in `/context` output and you want to know why, |
| 15 | +- you're tuning the skill or adding a new document type, |
| 16 | +- you're debugging an unexpected ordering of results. |
| 17 | + |
| 18 | +Source of truth: `cli/internal/mcp/tools/search_documents.go` (Layer 1) and `plugin/skills/context/SKILL.md` (Layer 2). The skill markdown is canonical for rendering decisions. |
| 19 | + |
| 20 | +## Pipeline |
| 21 | + |
| 22 | +``` |
| 23 | +┌─────────────────────────────────────────────────────────────────┐ |
| 24 | +│ Layer 1 — MCP search_documents (cli/internal/mcp/tools/...) │ |
| 25 | +│ Returns ALL document types. /context passes no `types` filter. │ |
| 26 | +│ Sorts by relevance: max_specificity DESC → typeRank ASC → │ |
| 27 | +│ mtime DESC. Default limit 50. │ |
| 28 | +└─────────────────────────────────────────────────────────────────┘ |
| 29 | + ↓ |
| 30 | +┌─────────────────────────────────────────────────────────────────┐ |
| 31 | +│ Layer 2 — /archcore:context Step 3-4 grouping (markdown skill) │ |
| 32 | +│ Applies a type allow-list (path & topic modes); pickup mode has │ |
| 33 | +│ its own fixed sections. Top 5 per section. │ |
| 34 | +└─────────────────────────────────────────────────────────────────┘ |
| 35 | + ↓ |
| 36 | + rendered markdown surface |
| 37 | +``` |
| 38 | + |
| 39 | +## Layer 1 — MCP `search_documents` (CLI) |
| 40 | + |
| 41 | +### Inputs the skill passes |
| 42 | + |
| 43 | +| Mode | Filter | |
| 44 | +|---|---| |
| 45 | +| path | `path_ref="<normalized>"`, `limit=50`, `sort="relevance"` | |
| 46 | +| topic | `content="<argument>"`, `limit=50`, `sort="relevance"` | |
| 47 | +| pickup | drafts: `types=["plan","idea"]`, `status="draft"`, `sort="mtime"`; recent-accepted: `types=["adr","rule"]`, `status="accepted"`, `mtime_after="30d"` (fallback `90d`) | |
| 48 | + |
| 49 | +Notes: |
| 50 | +- Content search is strict substring — no stemming, no fuzzy matching. The skill retries once with a shorter or alternate phrasing if the first call returns empty. |
| 51 | +- Path mode normalizes `\` → `/` and strips trailing `/` before sending. |
| 52 | + |
| 53 | +### Sort keys (relevance mode) |
| 54 | + |
| 55 | +Ordering, in priority: |
| 56 | + |
| 57 | +1. **`max_specificity` DESC.** |
| 58 | + - Content match in title → `3`. |
| 59 | + - Content match in body only → `1`. |
| 60 | + - `path_ref` match → number of `/`-separated segments shared between the reference and the query (e.g. `src/payments/stripe.ts` ↔ `src/payments/` → `2`). |
| 61 | +2. **`typeRank` ASC** (table below). |
| 62 | +3. **`mtime` DESC.** |
| 63 | + |
| 64 | +`typeRank` is only a tiebreaker — it never filters anything out by itself. |
| 65 | + |
| 66 | +### Type priority (`typeRank`) |
| 67 | + |
| 68 | +| Rank | Type | Notes | |
| 69 | +|---|---|---| |
| 70 | +| 1 | `rule` | Highest — normative | |
| 71 | +| 2 | `adr` | Decision | |
| 72 | +| 3 | `rfc` | Open proposal | |
| 73 | +| 4 | `spec` | Contract | |
| 74 | +| 5 | `cpat` | Code-pattern change | |
| 75 | +| 6 | `guide` | How-to | |
| 76 | +| 7 | `plan` | | |
| 77 | +| 8 | `idea` | | |
| 78 | +| 9 | `prd` | | |
| 79 | +| 10–16 | `brs`, `syrs`, `srs`, `strs`, `mrd`, `brd`, `urd` | Requirements (ISO + market/business/user) | |
| 80 | +| 17 | `doc` | Reference | |
| 81 | +| 18 | `task-type` | | |
| 82 | +| 100 | (any unknown) | `typePriorityDefault` | |
| 83 | + |
| 84 | +## Layer 2 — Step 3 grouping (path / topic modes) |
| 85 | + |
| 86 | +The skill takes the relevance-sorted list and slots each document into a section: |
| 87 | + |
| 88 | +| Section | Types | Cap | |
| 89 | +|---|---|---| |
| 90 | +| Rules | `rule` | top 5 | |
| 91 | +| Decisions | `adr` | top 5 | |
| 92 | +| Specs | `spec` | top 5 | |
| 93 | +| Patterns | `cpat` | top 5 | |
| 94 | +| Reference | `doc`, `rfc`, orphan `guide` (see Step 4) | top 5 | |
| 95 | +| In Progress | `plan` / `idea` with `status=draft` | top 5 | |
| 96 | + |
| 97 | +**Dropped types** (never rendered in path/topic mode): |
| 98 | + |
| 99 | +- accepted `plan` / `idea` — once shipped they exit the surface, |
| 100 | +- `task-type` — experiential, not in scope for "before you touch code" context, |
| 101 | +- vision/requirements: `prd`, `mrd`, `brd`, `urd`, `brs`, `strs`, `syrs`, `srs` — they describe intent, not normative knowledge. |
| 102 | + |
| 103 | +Empty sections are suppressed: no header is rendered if its array is empty. |
| 104 | + |
| 105 | +## Layer 2 — Step 4 guide routing & orphan-guide concept |
| 106 | + |
| 107 | +`guide` is handled in two passes: |
| 108 | + |
| 109 | +1. **Inlined guide.** For each item in the Rules / Decisions / Specs sections, walk its `incoming_relations`. If a `guide` points at it via `implements` or `related`, the guide is rendered as an indented bullet under the parent (📖). The skill tracks the set of inlined guide paths to avoid double-counting. |
| 110 | +2. **Orphan guide.** Any `guide` returned by `search_documents` but **not** in the inlined set falls through to the **Reference** section. |
| 111 | + |
| 112 | +Effect: a guide whose normative parent matched the same query stays attached to it; a standalone guide still surfaces (just lower in the output) instead of being silently dropped, which was the pre-2026-05-20 behavior. |
| 113 | + |
| 114 | +## Pickup mode (no argument) |
| 115 | + |
| 116 | +Pickup has its own fixed sections and does NOT use the Step 3 allow-list. Two `search_documents` calls in parallel: |
| 117 | + |
| 118 | +| Section | Source call | |
| 119 | +|---|---| |
| 120 | +| In Progress | `types=["plan","idea"]`, `status="draft"`, sort by mtime | |
| 121 | +| Recent Decisions | `types=["adr"]` from the recent-accepted call (30d → 90d fallback) | |
| 122 | +| Recent Rules | `types=["rule"]` from the same call | |
| 123 | + |
| 124 | +So `doc` / `rfc` / orphan-guide are not surfaced by pickup — that's intentional. Pickup answers "what work is current?", not "what knowledge applies?". |
| 125 | + |
| 126 | +## Examples |
| 127 | + |
| 128 | +### Example 1 — topic query "recaptcha" (post-fix) |
| 129 | + |
| 130 | +`search_documents(content="recaptcha")` returns, ordered: |
| 131 | + |
| 132 | +1. `recaptcha-handling.doc.md` — title match → `specificity=3`, `typeRank=17`. |
| 133 | +2. `error-handling.rule.md` — body match → `specificity=1`, `typeRank=1`. |
| 134 | +3. `auth-popup-unit-coverage.plan.md` — body match → `specificity=1`, `typeRank=7`, `status=draft`. |
| 135 | +4. `auth-provider-decomposition.idea.md` — body match → `specificity=1`, `typeRank=8`, `status=draft`. |
| 136 | + |
| 137 | +After Step 3: |
| 138 | + |
| 139 | +``` |
| 140 | +## Rules (1) — error-handling.rule.md |
| 141 | +## Reference (1) — recaptcha-handling.doc.md |
| 142 | +## In Progress (2) — auth-popup-unit-coverage.plan.md, auth-provider-decomposition.idea.md |
| 143 | +``` |
| 144 | + |
| 145 | +Pre-2026-05-20: Reference did not exist and `recaptcha-handling.doc.md` was silently dropped despite being the top relevance hit. |
| 146 | + |
| 147 | +### Example 2 — path query `src/auth/popup/` |
| 148 | + |
| 149 | +Same allow-list applies. `doc` files referencing that path (via `@src/auth/popup/...` or qualified bare mentions) land in Reference; rules / ADRs go to their normative sections. |
| 150 | + |
| 151 | +### Example 3 — accepted `plan` for the same topic |
| 152 | + |
| 153 | +Dropped at Step 3. Rationale: `/context` is "what knowledge applies to this code area", not "what was done about it". An accepted plan is historical record — discoverable via `/audit` or `list_documents`. |
| 154 | + |
| 155 | +## Maintenance hooks |
| 156 | + |
| 157 | +- **Adding a new document type** (CLI side): set its `typePriority` in `search_documents.go` for deterministic tie-break, and decide its Layer 2 fate in `skills/context/SKILL.md` Step 3 (allow-list, Reference, or drop). |
| 158 | +- **Changing what `/context` surfaces** is a skill-only change (markdown) — no CLI release required. Update Step 3 table, Step 5 render template, and the README Commands-table copy together; see `context-skill-implementation.plan.md` post-merge notes for the audit trail. |
0 commit comments