Skip to content

Commit 16f828b

Browse files
committed
fix: context filtering for context command
1 parent 9a0a90c commit 16f828b

5 files changed

Lines changed: 192 additions & 10 deletions

File tree

.archcore/.sync-state.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3351,6 +3351,21 @@
33513351
"source": "plugin/skill-surface-collapse.adr.md",
33523352
"target": "plugin/component-registry.doc.md",
33533353
"type": "related"
3354+
},
3355+
{
3356+
"source": "plugin/context-filtering-pipeline.doc.md",
3357+
"target": "plugin/context-skill-implementation.plan.md",
3358+
"type": "related"
3359+
},
3360+
{
3361+
"source": "plugin/context-filtering-pipeline.doc.md",
3362+
"target": "plugin/skills-system.spec.md",
3363+
"type": "related"
3364+
},
3365+
{
3366+
"source": "plugin/context-filtering-pipeline.doc.md",
3367+
"target": "plugin/commands-system.spec.md",
3368+
"type": "related"
33543369
}
33553370
]
33563371
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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.

.archcore/plugin/context-skill-implementation.plan.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ Deferred (non-blocking, tracked here for follow-up):
3333
3434
> **Note (skill-surface-collapse cleanup, 2026-05-15):** `/archcore:review` was subsequently merged into `/archcore:audit` and `/archcore:actualize` was folded into `/archcore:audit --drift` (see `skill-surface-collapse.adr.md`). References below to `/archcore:review`, `/archcore:review --deep`, `/archcore:actualize`, `/archcore:standard`, and `/archcore:bootstrap` should be read as their successors: `audit` (default), `audit --deep`, `audit --drift`, `decide`, and `init` respectively.
3535
36+
> **Note (Reference section, 2026-05-20):** Step 3 grouping in `skills/context/SKILL.md` extended with a **Reference** section that surfaces `doc`, `rfc`, and orphan `guide` (any guide present in search results but not inlined under a rule/ADR/spec via Step 4's `implements`/`related` routing). This closes a gap where the most relevant content match could be silently dropped because its type wasn't in the original allow-list — observed when a `doc` topped relevance for a topic query but never reached the rendered output. Acceptance criterion below ("rule+adr+spec+cpat groups") should be read as including a Reference group in addition; post-merge smoke tests gained a `doc`/`rfc`/orphan-guide repro.
37+
3638
## Goal
3739

3840
Ship `/archcore:context` as the user-facing pull-mode entry point for JTBD #1 ("repo-alignment at coding time"), backed by the CLI's `search_documents` MCP tool. Close the JTBD-implementation gap for on-demand code-area lookup and session pickup, without touching PreToolUse hooks (deferred to Phase 2).
@@ -60,10 +62,10 @@ Frontmatter:
6062

6163
Body sections:
6264
- **Classify scope** — empty/whitespace → pickup; contains `/` OR is an existing repo directory → path; otherwise → topic.
63-
- **Path mode**`search_documents(path_ref, limit=50, sort="relevance")`, group by type (rule/adr/spec/cpat/plan-draft/idea-draft), truncate each section to top-5, render.
65+
- **Path mode**`search_documents(path_ref, limit=50, sort="relevance")`, group by type (rule/adr/spec/cpat/plan-draft/idea-draft), truncate each section to top-5, render. _(2026-05-20: Reference section added — see top-of-doc note.)_
6466
- **Topic mode** — same but `content="<scope>"`.
6567
- **Pickup mode** — two primitive calls: drafts + recent-accepted (30d → fallback 90d). Render as In Progress / Recent Decisions / Recent Rules.
66-
- **Guide routing** — for each rule/adr/spec top-5, check `incoming_relations` for a `guide` linked via `implements`/`related`; inline as indented bullet.
68+
- **Guide routing** — for each rule/adr/spec top-5, check `incoming_relations` for a `guide` linked via `implements`/`related`; inline as indented bullet. _(2026-05-20: track the inlined set so non-inlined guides land in Reference rather than being dropped.)_
6769
- **Empty-header suppression** — do NOT emit a section header if its array is empty.
6870
- **Classification footer**`_Classified as: <mode>._` for observability.
6971
- **Disambiguation note** — "Not related to the AI context window or session state" in body, so the skill does not get mis-invoked for chat memory topics.
@@ -101,10 +103,10 @@ Two or three fixture `.archcore/` repos under `tests/fixtures/context/`. Run the
101103

102104
**SKILL.md**
103105
- `skills/context/SKILL.md` exists, picked up by plugin auto-discovery.
104-
- `/archcore:context src/payments/` returns rule+adr+spec+cpat groups sorted by specificity→type→mtime, top-5 per section.
105-
- `/archcore:context "money rounding"` returns content-match groups with title/body excerpts.
106+
- `/archcore:context src/payments/` returns rule+adr+spec+cpat groups (and a Reference group for `doc`/`rfc`/orphan `guide`) sorted by specificity→type→mtime, top-5 per section.
107+
- `/archcore:context "money rounding"` returns content-match groups with title/body excerpts; `doc`/`rfc` matches surface in Reference rather than being dropped.
106108
- `/archcore:context` (no argument) returns In Progress + Recent Decisions + Recent Rules, with 30d→90d fallback when first pass is empty.
107-
- Guide routing: when a rule/adr/spec has an incoming `guide` via `implements` or `related`, guide appears as an indented bullet below the parent.
109+
- Guide routing: when a rule/adr/spec has an incoming `guide` via `implements` or `related`, guide appears as an indented bullet below the parent; an orphan `guide` (no such relation) appears in the Reference section instead of being dropped.
108110
- No section header is rendered when its group is empty.
109111
- Classification footer is always present.
110112

@@ -156,3 +158,4 @@ Run in Claude Code against this plugin repo:
156158
- `/archcore:context rules/` — should surface mcp-only-operations.rule, skill-file-structure.rule.
157159
- `/archcore:context "intent-based skill"` — should find intent-based-skill-architecture.adr.
158160
- `/archcore:context` with no argument — should show draft plans + recent accepted rules/ADRs.
161+
- _(2026-05-20)_ In a repo with a top-relevance `doc` for the queried topic, confirm it now appears in a **Reference** section rather than being filtered out. Same for a `rfc` covering the topic and a `guide` not linked via `implements`/`related` to any rule/ADR/spec.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Describe what you want in plain English — Archcore routes it. The slash comman
1515
| Command | Outcome | When to use |
1616
| -------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
1717
| `/archcore:init` | Make your repo legible to AI agents | First-time setup — seeds a stack rule, a run-the-app guide, and imports your `CLAUDE.md` / `AGENTS.md` / `.cursorrules` if present |
18-
| `/archcore:context` | Load what's already decided before you change code | Daily, before editing — pulls relevant rules, decisions, specs, and patterns for a file, directory, or topic |
18+
| `/archcore:context` | Load what's already decided before you change code | Daily, before editing — pulls relevant rules, decisions, specs, patterns, and reference docs for a file, directory, or topic |
1919
| `/archcore:capture` | Document what already lives in code | A module, API, pipeline, or integration has tribal knowledge but no doc yet |
2020
| `/archcore:plan` | Turn an idea into a scoped implementation plan | New feature, refactor, or initiative — pick depth with `--track product\|feature\|sources\|iso` |
2121
| `/archcore:decide` | Record a decision and (optionally) make it a team rule | A decision was made — capture rationale, consequences, and turn it into an enforced standard |

skills/context/SKILL.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
name: context
33
argument-hint: "[file, directory, or topic; leave empty for current-focus pickup]"
4-
description: "Surface the rules, ADRs, specs, and patterns that apply to a code area before changing it — or recap project focus when picking up work. Use for 'what rules apply to X', 'before I touch Y', 'pick up where we left off', 'load project context'. Not for creating docs, planning, or audits."
4+
description: "Surface the rules, ADRs, specs, patterns, and reference docs that apply to a code area before changing it — or recap project focus when picking up work. Use for 'what rules apply to X', 'before I touch Y', 'pick up where we left off', 'load project context'. Not for creating docs, planning, or audits."
55
---
66

77
# /archcore:context
@@ -74,9 +74,10 @@ If the recent-accepted call returns empty, retry once with `mtime_after="90d"`.
7474
| Decisions | `adr` |
7575
| Specs | `spec` |
7676
| Patterns | `cpat` |
77+
| Reference | `doc`, `rfc`, orphan `guide` (any `guide` not inlined by Step 4) |
7778
| In Progress | `plan` or `idea` with status `draft` |
7879

79-
Drop other types. Results are already sorted by `search_documents` (specificity → type priority → mtime); keep the top 5 per section.
80+
Drop remaining types — accepted `plan`/`idea`, `task-type`, and vision/requirements (`prd`, `mrd`, `brd`, `urd`, `brs`, `strs`, `syrs`, `srs`). Results are already sorted by `search_documents` (specificity → type priority → mtime); keep the top 5 per section. Inside Reference the same sort applies, so `rfc` (typeRank 3) outranks `guide` (6) and `doc` (17) when specificity ties.
8081

8182
**Pickup mode** — three fixed sections:
8283
- **In Progress** — results from the drafts call
@@ -85,7 +86,7 @@ Drop other types. Results are already sorted by `search_documents` (specificity
8586

8687
### Step 4: Guide routing
8788

88-
For each item in the Rules, Decisions, or Specs sections, inspect its `incoming_relations`. If a relation of type `implements` or `related` points from a `guide`, inline that guide as an indented bullet under the parent. Skip a guide that is already inlined under a sibling in the same section.
89+
For each item in the Rules, Decisions, or Specs sections, inspect its `incoming_relations`. If a relation of type `implements` or `related` points from a `guide`, inline that guide as an indented bullet under the parent. Skip a guide that is already inlined under a sibling in the same section. Track the set of guide paths inlined this way — any `guide` present in the search results but **not** in this set is an "orphan guide" and is routed to the Reference section in Step 3 instead of being dropped.
8990

9091
### Step 5: Render
9192

@@ -107,6 +108,11 @@ For each item in the Rules, Decisions, or Specs sections, inspect its `incoming_
107108
## Patterns (N)
108109
...
109110
111+
## Reference (N)
112+
- **<title>** [<type> · <status> · <match.kind>]
113+
`<path>`
114+
> <excerpt>
115+
110116
## In Progress (N)
111117
⚠️ **<title>** [plan · draft]
112118
`<path>`
@@ -126,4 +132,4 @@ If all sections are empty, fall through to Step 6.
126132

127133
## Result
128134

129-
A grouped markdown surface of the rules, ADRs, specs, patterns, and in-progress work that applies to the requested scope — or a pickup summary of draft work + recent accepted decisions and rules when called with no argument. A classification footer identifies which mode was chosen.
135+
A grouped markdown surface of the rules, ADRs, specs, patterns, reference docs (`doc`, `rfc`, orphan `guide`), and in-progress work that applies to the requested scope — or a pickup summary of draft work + recent accepted decisions and rules when called with no argument. A classification footer identifies which mode was chosen.

0 commit comments

Comments
 (0)