@drafthq/draft 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +19 -1
- package/core/shared/draft-context-loading.md +9 -0
- package/core/shared/okf-retrieval.md +94 -0
- package/integrations/agents/AGENTS.md +117 -1
- package/integrations/copilot/.github/copilot-instructions.md +117 -1
- package/package.json +1 -1
- package/scripts/lib.sh +1 -0
- package/skills/init/SKILL.md +5 -1
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"name": "draft",
|
|
13
13
|
"source": "./",
|
|
14
14
|
"description": "Context-Driven Development: draft specs and plans before implementation. Structured workflows for features and fixes.",
|
|
15
|
-
"version": "3.
|
|
15
|
+
"version": "3.4.0",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "mayurpise"
|
|
18
18
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "draft",
|
|
3
3
|
"displayName": "Draft",
|
|
4
4
|
"description": "Context-Driven Development: draft specs and plans before implementation. Structured workflows for features and fixes.",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.4.0",
|
|
6
6
|
"skills": "./skills/",
|
|
7
7
|
"agents": "./core/agents/",
|
|
8
8
|
"author": {
|
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ Each host installs the way that host actually loads extensions — no manual ste
|
|
|
67
67
|
| Host | `draft install …` | What it does |
|
|
68
68
|
|------|-------------------|--------------|
|
|
69
69
|
| **Claude Code** | `claude-code` | Registers the plugin via `claude plugin marketplace add` + `claude plugin install` (user scope). Restart Claude Code. |
|
|
70
|
-
| **Cursor** | `cursor` | Copies the plugin into `~/.cursor/plugins/local/draft/`, writes `.cursor-plugin/plugin.json`, registers `draft@draft-plugins` in Cursor's plugin registry, and enables it. Restart Cursor (or Developer: Reload Window). |
|
|
70
|
+
| **Cursor** | `cursor` | Copies the plugin into `~/.cursor/plugins/local/draft/`, writes `.cursor-plugin/plugin.json`, registers `draft@draft-plugins` in Cursor's plugin registry, and enables it. Restart Cursor (or Developer: Reload Window). Existing installs upgrade with `draft install cursor --force`. |
|
|
71
71
|
| **Codex** | `codex` | Writes `./AGENTS.md`, which Codex reads automatically. |
|
|
72
72
|
| **opencode** | `opencode` | Writes `./AGENTS.md` + `~/.agents/skills/draft/`, both auto-discovered. |
|
|
73
73
|
|
|
@@ -223,6 +223,24 @@ Skills also call into **shell helpers** under `scripts/tools/` for mechanical wo
|
|
|
223
223
|
files with changed hashes
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
+
### Context output modes (`/draft:init`)
|
|
227
|
+
|
|
228
|
+
`/draft:init` packages your architecture context in one of two modes, selected
|
|
229
|
+
automatically by repo size (override with `DRAFT_INIT_MODE`):
|
|
230
|
+
|
|
231
|
+
- **`monolith`** (default for small repos, tiers 1–2) — a single
|
|
232
|
+
graph-primary `architecture.md` is the source of truth; `.ai-context.md` is
|
|
233
|
+
the token-optimized AI view derived from it.
|
|
234
|
+
- **`okf`** (default for larger repos, tiers 3+) — an **OKF concept taxonomy**
|
|
235
|
+
under `draft/wiki/` is the source of truth (one concept per file, cross-links
|
|
236
|
+
form the graph), `.ai-context.md` becomes the navigable index root
|
|
237
|
+
(Synopsis + Concept Map), and `architecture.md` is demoted to a generated
|
|
238
|
+
rendered view. An optional self-contained offline HTML viewer ships under
|
|
239
|
+
`draft/wiki/web/`.
|
|
240
|
+
|
|
241
|
+
Both modes produce the same `product.md`, `tech-stack.md`, `workflow.md`,
|
|
242
|
+
`guardrails.md`, tracks, and `.state/` — only the architecture packaging differs.
|
|
243
|
+
|
|
226
244
|
[Full workflow →](core/methodology.md#core-workflow)
|
|
227
245
|
|
|
228
246
|
---
|
|
@@ -117,6 +117,15 @@ Apply relevance scoring when ALL of these conditions are true:
|
|
|
117
117
|
|
|
118
118
|
Do NOT apply relevance scoring for commands that need full context (`/draft:init`, `/draft:deep-review`, `/draft:decompose`).
|
|
119
119
|
|
|
120
|
+
### Retrieval Path Selection (okf vs monolith)
|
|
121
|
+
|
|
122
|
+
Relevance scoring has two implementations; pick by output mode:
|
|
123
|
+
|
|
124
|
+
- **okf mode** — if `draft/wiki/` exists, use **tree-search retrieval** (`core/shared/okf-retrieval.md`): navigate the OKF Concept Map by reasoning over each concept's routing `description`, descending only the matching subtrees. This is the vectorless, reasoning-based path (PageIndex-style) and supersedes the static section table below for okf bundles.
|
|
125
|
+
- **monolith mode** — if `draft/wiki/` does not exist, use the static **Scoring Procedure** below against `.ai-context.md` sections.
|
|
126
|
+
|
|
127
|
+
The minimum context floor (`META`, `INVARIANTS`, `TEST`, `FILES`) applies to both paths.
|
|
128
|
+
|
|
120
129
|
### Scoring Procedure
|
|
121
130
|
|
|
122
131
|
1. **Extract key concepts** from the active task:
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# OKF Tree-Search Retrieval
|
|
2
|
+
|
|
3
|
+
Reasoning-based retrieval over the OKF knowledge bundle. When a project was emitted in `okf` mode (`draft/wiki/` exists), agents locate relevant context by **navigating the concept tree** — reading routing descriptions and descending only the matching subtrees — instead of loading sections by a static heuristic. No embeddings, no chunking, no similarity search: relevance is decided by reasoning over the tree, the same way a human expert scans a table of contents.
|
|
4
|
+
|
|
5
|
+
Referenced by: `core/shared/draft-context-loading.md` (Relevance-Scored Context Loading). Applies to every command that loads focused project context (`/draft:implement`, `/draft:bughunt`, `/draft:review`, `/draft:debug`, `/draft:change`).
|
|
6
|
+
|
|
7
|
+
> **Prior art.** This adapts the navigation model of [PageIndex](https://github.com/VectifyAI/PageIndex) (vectorless, reasoning-based RAG) to Draft's self-authored artifacts. Draft already builds the tree — the OKF bundle (`index.md` → section indexes → concept pages) is a table-of-contents whose `description` frontmatter is the per-node routing key. What this procedure adds is the **retrieval loop**: a reasoning descent over that tree. Draft does not need PageIndex's tree-*generation* engine (it authors the tree itself) and stays vectorless by design.
|
|
8
|
+
|
|
9
|
+
## When this applies
|
|
10
|
+
|
|
11
|
+
Apply tree-search retrieval when ALL of these hold:
|
|
12
|
+
|
|
13
|
+
1. `draft/wiki/` exists (project emitted in `okf` mode) **and** `draft/wiki/index.md` carries a populated `<!-- CONCEPT-MAP:START -->…:END -->` block.
|
|
14
|
+
2. A specific track or task is active (focused retrieval — broad tasks terminate at the Synopsis, see below).
|
|
15
|
+
3. The command benefits from focused context (the relevance-scoring conditions in `draft-context-loading.md`).
|
|
16
|
+
|
|
17
|
+
If `draft/wiki/` does **not** exist (monolith mode), skip this procedure entirely and use the static section-scoring table in `draft-context-loading.md`. The two are mutually exclusive: tree-search is the okf-mode retrieval path; section-scoring is the monolith path.
|
|
18
|
+
|
|
19
|
+
## The retrieval loop
|
|
20
|
+
|
|
21
|
+
The bundle is a tree: `.ai-context.md` (index root: Synopsis + Concept Map) → section indexes (`systems/`, `features/`, `reference/`, `entrypoints/`, `overview/`) → concept pages. Each node advertises a `description` routing key. Navigate it, do not flatten it.
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
1. Frame the query
|
|
25
|
+
Extract routing terms from the active task: domain nouns from spec.md
|
|
26
|
+
acceptance criteria, file paths / module names / tech terms from plan.md,
|
|
27
|
+
and the primary concern (data flow, API, security, perf, config, …).
|
|
28
|
+
|
|
29
|
+
2. Enter at the root
|
|
30
|
+
Read draft/.ai-context.md. The Synopsis is the cheap broad-context path —
|
|
31
|
+
for a BROAD task (onboarding, architecture overview, "how does X work
|
|
32
|
+
end-to-end") it is sufficient: TERMINATE here, do not descend.
|
|
33
|
+
For a FOCUSED task, read the Concept Map (the root routing table).
|
|
34
|
+
|
|
35
|
+
3. Select subtrees (reason, don't match strings)
|
|
36
|
+
For each Concept Map row, judge the `description` as a ROUTING DECISION:
|
|
37
|
+
"does opening this concept help THIS task?" Score each candidate:
|
|
38
|
+
- strong — description names the task's responsibility or its own terms
|
|
39
|
+
- possible — adjacent/depends-on the task area
|
|
40
|
+
- skip — unrelated
|
|
41
|
+
Descend `strong` first; hold `possible` as a frontier for step 5.
|
|
42
|
+
|
|
43
|
+
4. Descend to leaves
|
|
44
|
+
For a selected section, open its index.md and repeat step 3 against the
|
|
45
|
+
section's concept rows (one routing description per concept). Open the
|
|
46
|
+
matching concept page(s). A concept page is a LEAF — its `x-grounded-paths`
|
|
47
|
+
are the exact source files the task should open; `Used by` / `x-callers`
|
|
48
|
+
give the next hop if the task spans callers.
|
|
49
|
+
|
|
50
|
+
5. Expand only if under-covered
|
|
51
|
+
If the opened leaves do not cover the task's routing terms, expand the
|
|
52
|
+
highest-scored `possible` frontier node (step 3) and recurse. Otherwise stop.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Routing decision criteria
|
|
56
|
+
|
|
57
|
+
The `description` frontmatter is load-bearing — it is written as a routing decision, not a summary (`core/templates/okf/concept.md`). Judge each node by:
|
|
58
|
+
|
|
59
|
+
| Signal | Descend when… |
|
|
60
|
+
|--------|---------------|
|
|
61
|
+
| Responsibility match | The description names the capability/module the task changes |
|
|
62
|
+
| Term overlap | Task's domain nouns / file paths appear in the description or `x-grounded-paths` |
|
|
63
|
+
| Caller/blast-radius reach | Task modifies a symbol whose `x-callers` / `Used by` point at this node |
|
|
64
|
+
| Concern alignment | Task's primary concern (security, perf, data flow) is this node's stated focus |
|
|
65
|
+
|
|
66
|
+
Reason about relevance — do not keyword-match. A concept whose description does not justify opening it for the task at hand is skipped even if a term coincidentally overlaps (similarity ≠ relevance).
|
|
67
|
+
|
|
68
|
+
## Termination & budget
|
|
69
|
+
|
|
70
|
+
- **Broad task** → terminate at the Synopsis (step 2). Do not open concept pages.
|
|
71
|
+
- **Focused task** → terminate when opened leaves cover the task's routing terms, or when **≤ 5 concept pages** have been opened (default budget; raise only if the task explicitly spans many subsystems, e.g. a cross-cutting refactor).
|
|
72
|
+
- **Depth** → the tree is shallow by construction (root → section → concept ≈ 2 hops). If a descent has not reached a leaf in 3 hops, stop and open the best leaf seen so far.
|
|
73
|
+
- **No match** → if no Concept Map row scores above `skip`, fall back to the Synopsis plus `## INVARIANTS` / `## FILES` / `## TEST` floor from `draft-context-loading.md`.
|
|
74
|
+
|
|
75
|
+
The minimum context floor from `draft-context-loading.md` (`META`, `INVARIANTS`, `TEST`, `FILES`) still applies and is always loaded regardless of the descent.
|
|
76
|
+
|
|
77
|
+
## Output contract (traceability)
|
|
78
|
+
|
|
79
|
+
Tree-search retrieval is explainable by construction — record the path taken, mirroring PageIndex's node-ID grounding:
|
|
80
|
+
|
|
81
|
+
- **Opened concepts** — the leaf pages selected, each with the one-line reason it was opened.
|
|
82
|
+
- **Grounded paths** — the union of `x-grounded-paths` across opened leaves: the precise source files the task will read or modify.
|
|
83
|
+
- **Skipped frontier** — `possible` nodes held but not expanded (so a follow-up task can resume from them).
|
|
84
|
+
|
|
85
|
+
Surface this trace when the command reports which context it loaded (e.g. `/draft:implement` plan preamble, `/draft:review` scope note). It replaces "loaded sections A, B, C" with "navigated to concepts X, Y because …".
|
|
86
|
+
|
|
87
|
+
## Degradation
|
|
88
|
+
|
|
89
|
+
| Scenario | Behavior |
|
|
90
|
+
|----------|----------|
|
|
91
|
+
| `draft/wiki/` missing | Skip; use monolith section-scoring in `draft-context-loading.md` |
|
|
92
|
+
| Concept Map markers empty/absent | Fall back to reading `wiki/*/index.md` section tables directly; if those are missing, use the Synopsis + floor |
|
|
93
|
+
| Routing descriptions thin/uninformative | Open the section `index.md` and skim concept titles; flag for `/draft:init refresh` to regenerate descriptions |
|
|
94
|
+
| Task is broad | Terminate at Synopsis — descending is over-fetch (a Red Flag per `red-flags.md`) |
|
|
@@ -455,7 +455,11 @@ If the user runs `draft init refresh`:
|
|
|
455
455
|
|
|
456
456
|
1. **Tech Stack Refresh**: Re-scan `package.json`, `go.mod`, etc. Compare with `draft/tech-stack.md`. Propose updates.
|
|
457
457
|
|
|
458
|
-
2. **Architecture Refresh**:
|
|
458
|
+
2. **Architecture Refresh**:
|
|
459
|
+
|
|
460
|
+
**Mode detection (do this first).** If `draft/wiki/` exists, the bundle was generated in **`okf` mode** and `architecture.md` is a *generated rendered view*, not the source of truth. In that case **follow `references/okf-emitter.md` §"Incremental refresh at concept granularity (M5)"** instead of the monolith steps below: diff `hashes.json` → map changed source paths to affected concepts → regenerate only those concepts (carry the rest forward from cache) → always re-render `.ai-context.md`, `architecture.md`, and `log.md` via `okf-render-views.sh` → re-run `okf-validate.sh` so cross-links still resolve. Do **not** hand-edit `architecture.md` in this mode — it is overwritten by the renderer. Then skip to step 3.
|
|
461
|
+
|
|
462
|
+
Otherwise (**`monolith` mode** — `draft/architecture.md` is the source of truth and no `draft/wiki/` exists), use metadata-based incremental analysis. If freshness state is available from step 0b, use file-level deltas to scope the refresh more precisely than git-diff alone:
|
|
459
463
|
|
|
460
464
|
**a. Read synced commit from metadata:**
|
|
461
465
|
```bash
|
|
@@ -16270,6 +16274,15 @@ Apply relevance scoring when ALL of these conditions are true:
|
|
|
16270
16274
|
|
|
16271
16275
|
Do NOT apply relevance scoring for commands that need full context (`draft init`, `draft deep-review`, `draft decompose`).
|
|
16272
16276
|
|
|
16277
|
+
### Retrieval Path Selection (okf vs monolith)
|
|
16278
|
+
|
|
16279
|
+
Relevance scoring has two implementations; pick by output mode:
|
|
16280
|
+
|
|
16281
|
+
- **okf mode** — if `draft/wiki/` exists, use **tree-search retrieval** (`core/shared/okf-retrieval.md`): navigate the OKF Concept Map by reasoning over each concept's routing `description`, descending only the matching subtrees. This is the vectorless, reasoning-based path (PageIndex-style) and supersedes the static section table below for okf bundles.
|
|
16282
|
+
- **monolith mode** — if `draft/wiki/` does not exist, use the static **Scoring Procedure** below against `.ai-context.md` sections.
|
|
16283
|
+
|
|
16284
|
+
The minimum context floor (`META`, `INVARIANTS`, `TEST`, `FILES`) applies to both paths.
|
|
16285
|
+
|
|
16273
16286
|
### Scoring Procedure
|
|
16274
16287
|
|
|
16275
16288
|
1. **Extract key concepts** from the active task:
|
|
@@ -17643,6 +17656,109 @@ The engine indexes C/C++, Go, Python, TypeScript/JS, and more (tree-sitter, 159
|
|
|
17643
17656
|
|
|
17644
17657
|
---
|
|
17645
17658
|
|
|
17659
|
+
## core/shared/okf-retrieval.md
|
|
17660
|
+
|
|
17661
|
+
<core-file path="core/shared/okf-retrieval.md">
|
|
17662
|
+
|
|
17663
|
+
# OKF Tree-Search Retrieval
|
|
17664
|
+
|
|
17665
|
+
Reasoning-based retrieval over the OKF knowledge bundle. When a project was emitted in `okf` mode (`draft/wiki/` exists), agents locate relevant context by **navigating the concept tree** — reading routing descriptions and descending only the matching subtrees — instead of loading sections by a static heuristic. No embeddings, no chunking, no similarity search: relevance is decided by reasoning over the tree, the same way a human expert scans a table of contents.
|
|
17666
|
+
|
|
17667
|
+
Referenced by: `core/shared/draft-context-loading.md` (Relevance-Scored Context Loading). Applies to every command that loads focused project context (`draft implement`, `draft bughunt`, `draft review`, `draft debug`, `draft change`).
|
|
17668
|
+
|
|
17669
|
+
> **Prior art.** This adapts the navigation model of [PageIndex](https://github.com/VectifyAI/PageIndex) (vectorless, reasoning-based RAG) to Draft's self-authored artifacts. Draft already builds the tree — the OKF bundle (`index.md` → section indexes → concept pages) is a table-of-contents whose `description` frontmatter is the per-node routing key. What this procedure adds is the **retrieval loop**: a reasoning descent over that tree. Draft does not need PageIndex's tree-*generation* engine (it authors the tree itself) and stays vectorless by design.
|
|
17670
|
+
|
|
17671
|
+
## When this applies
|
|
17672
|
+
|
|
17673
|
+
Apply tree-search retrieval when ALL of these hold:
|
|
17674
|
+
|
|
17675
|
+
1. `draft/wiki/` exists (project emitted in `okf` mode) **and** `draft/wiki/index.md` carries a populated `<!-- CONCEPT-MAP:START -->…:END -->` block.
|
|
17676
|
+
2. A specific track or task is active (focused retrieval — broad tasks terminate at the Synopsis, see below).
|
|
17677
|
+
3. The command benefits from focused context (the relevance-scoring conditions in `draft-context-loading.md`).
|
|
17678
|
+
|
|
17679
|
+
If `draft/wiki/` does **not** exist (monolith mode), skip this procedure entirely and use the static section-scoring table in `draft-context-loading.md`. The two are mutually exclusive: tree-search is the okf-mode retrieval path; section-scoring is the monolith path.
|
|
17680
|
+
|
|
17681
|
+
## The retrieval loop
|
|
17682
|
+
|
|
17683
|
+
The bundle is a tree: `.ai-context.md` (index root: Synopsis + Concept Map) → section indexes (`systems/`, `features/`, `reference/`, `entrypoints/`, `overview/`) → concept pages. Each node advertises a `description` routing key. Navigate it, do not flatten it.
|
|
17684
|
+
|
|
17685
|
+
```
|
|
17686
|
+
1. Frame the query
|
|
17687
|
+
Extract routing terms from the active task: domain nouns from spec.md
|
|
17688
|
+
acceptance criteria, file paths / module names / tech terms from plan.md,
|
|
17689
|
+
and the primary concern (data flow, API, security, perf, config, …).
|
|
17690
|
+
|
|
17691
|
+
2. Enter at the root
|
|
17692
|
+
Read draft/.ai-context.md. The Synopsis is the cheap broad-context path —
|
|
17693
|
+
for a BROAD task (onboarding, architecture overview, "how does X work
|
|
17694
|
+
end-to-end") it is sufficient: TERMINATE here, do not descend.
|
|
17695
|
+
For a FOCUSED task, read the Concept Map (the root routing table).
|
|
17696
|
+
|
|
17697
|
+
3. Select subtrees (reason, don't match strings)
|
|
17698
|
+
For each Concept Map row, judge the `description` as a ROUTING DECISION:
|
|
17699
|
+
"does opening this concept help THIS task?" Score each candidate:
|
|
17700
|
+
- strong — description names the task's responsibility or its own terms
|
|
17701
|
+
- possible — adjacent/depends-on the task area
|
|
17702
|
+
- skip — unrelated
|
|
17703
|
+
Descend `strong` first; hold `possible` as a frontier for step 5.
|
|
17704
|
+
|
|
17705
|
+
4. Descend to leaves
|
|
17706
|
+
For a selected section, open its index.md and repeat step 3 against the
|
|
17707
|
+
section's concept rows (one routing description per concept). Open the
|
|
17708
|
+
matching concept page(s). A concept page is a LEAF — its `x-grounded-paths`
|
|
17709
|
+
are the exact source files the task should open; `Used by` / `x-callers`
|
|
17710
|
+
give the next hop if the task spans callers.
|
|
17711
|
+
|
|
17712
|
+
5. Expand only if under-covered
|
|
17713
|
+
If the opened leaves do not cover the task's routing terms, expand the
|
|
17714
|
+
highest-scored `possible` frontier node (step 3) and recurse. Otherwise stop.
|
|
17715
|
+
```
|
|
17716
|
+
|
|
17717
|
+
## Routing decision criteria
|
|
17718
|
+
|
|
17719
|
+
The `description` frontmatter is load-bearing — it is written as a routing decision, not a summary (`core/templates/okf/concept.md`). Judge each node by:
|
|
17720
|
+
|
|
17721
|
+
| Signal | Descend when… |
|
|
17722
|
+
|--------|---------------|
|
|
17723
|
+
| Responsibility match | The description names the capability/module the task changes |
|
|
17724
|
+
| Term overlap | Task's domain nouns / file paths appear in the description or `x-grounded-paths` |
|
|
17725
|
+
| Caller/blast-radius reach | Task modifies a symbol whose `x-callers` / `Used by` point at this node |
|
|
17726
|
+
| Concern alignment | Task's primary concern (security, perf, data flow) is this node's stated focus |
|
|
17727
|
+
|
|
17728
|
+
Reason about relevance — do not keyword-match. A concept whose description does not justify opening it for the task at hand is skipped even if a term coincidentally overlaps (similarity ≠ relevance).
|
|
17729
|
+
|
|
17730
|
+
## Termination & budget
|
|
17731
|
+
|
|
17732
|
+
- **Broad task** → terminate at the Synopsis (step 2). Do not open concept pages.
|
|
17733
|
+
- **Focused task** → terminate when opened leaves cover the task's routing terms, or when **≤ 5 concept pages** have been opened (default budget; raise only if the task explicitly spans many subsystems, e.g. a cross-cutting refactor).
|
|
17734
|
+
- **Depth** → the tree is shallow by construction (root → section → concept ≈ 2 hops). If a descent has not reached a leaf in 3 hops, stop and open the best leaf seen so far.
|
|
17735
|
+
- **No match** → if no Concept Map row scores above `skip`, fall back to the Synopsis plus `## INVARIANTS` / `## FILES` / `## TEST` floor from `draft-context-loading.md`.
|
|
17736
|
+
|
|
17737
|
+
The minimum context floor from `draft-context-loading.md` (`META`, `INVARIANTS`, `TEST`, `FILES`) still applies and is always loaded regardless of the descent.
|
|
17738
|
+
|
|
17739
|
+
## Output contract (traceability)
|
|
17740
|
+
|
|
17741
|
+
Tree-search retrieval is explainable by construction — record the path taken, mirroring PageIndex's node-ID grounding:
|
|
17742
|
+
|
|
17743
|
+
- **Opened concepts** — the leaf pages selected, each with the one-line reason it was opened.
|
|
17744
|
+
- **Grounded paths** — the union of `x-grounded-paths` across opened leaves: the precise source files the task will read or modify.
|
|
17745
|
+
- **Skipped frontier** — `possible` nodes held but not expanded (so a follow-up task can resume from them).
|
|
17746
|
+
|
|
17747
|
+
Surface this trace when the command reports which context it loaded (e.g. `draft implement` plan preamble, `draft review` scope note). It replaces "loaded sections A, B, C" with "navigated to concepts X, Y because …".
|
|
17748
|
+
|
|
17749
|
+
## Degradation
|
|
17750
|
+
|
|
17751
|
+
| Scenario | Behavior |
|
|
17752
|
+
|----------|----------|
|
|
17753
|
+
| `draft/wiki/` missing | Skip; use monolith section-scoring in `draft-context-loading.md` |
|
|
17754
|
+
| Concept Map markers empty/absent | Fall back to reading `wiki/*/index.md` section tables directly; if those are missing, use the Synopsis + floor |
|
|
17755
|
+
| Routing descriptions thin/uninformative | Open the section `index.md` and skim concept titles; flag for `draft init refresh` to regenerate descriptions |
|
|
17756
|
+
| Task is broad | Terminate at Synopsis — descending is over-fetch (a Red Flag per `red-flags.md`) |
|
|
17757
|
+
|
|
17758
|
+
</core-file>
|
|
17759
|
+
|
|
17760
|
+
---
|
|
17761
|
+
|
|
17646
17762
|
## core/shared/parallel-analysis.md
|
|
17647
17763
|
|
|
17648
17764
|
<core-file path="core/shared/parallel-analysis.md">
|
|
@@ -455,7 +455,11 @@ If the user runs `draft init refresh`:
|
|
|
455
455
|
|
|
456
456
|
1. **Tech Stack Refresh**: Re-scan `package.json`, `go.mod`, etc. Compare with `draft/tech-stack.md`. Propose updates.
|
|
457
457
|
|
|
458
|
-
2. **Architecture Refresh**:
|
|
458
|
+
2. **Architecture Refresh**:
|
|
459
|
+
|
|
460
|
+
**Mode detection (do this first).** If `draft/wiki/` exists, the bundle was generated in **`okf` mode** and `architecture.md` is a *generated rendered view*, not the source of truth. In that case **follow `references/okf-emitter.md` §"Incremental refresh at concept granularity (M5)"** instead of the monolith steps below: diff `hashes.json` → map changed source paths to affected concepts → regenerate only those concepts (carry the rest forward from cache) → always re-render `.ai-context.md`, `architecture.md`, and `log.md` via `okf-render-views.sh` → re-run `okf-validate.sh` so cross-links still resolve. Do **not** hand-edit `architecture.md` in this mode — it is overwritten by the renderer. Then skip to step 3.
|
|
461
|
+
|
|
462
|
+
Otherwise (**`monolith` mode** — `draft/architecture.md` is the source of truth and no `draft/wiki/` exists), use metadata-based incremental analysis. If freshness state is available from step 0b, use file-level deltas to scope the refresh more precisely than git-diff alone:
|
|
459
463
|
|
|
460
464
|
**a. Read synced commit from metadata:**
|
|
461
465
|
```bash
|
|
@@ -16270,6 +16274,15 @@ Apply relevance scoring when ALL of these conditions are true:
|
|
|
16270
16274
|
|
|
16271
16275
|
Do NOT apply relevance scoring for commands that need full context (`draft init`, `draft deep-review`, `draft decompose`).
|
|
16272
16276
|
|
|
16277
|
+
### Retrieval Path Selection (okf vs monolith)
|
|
16278
|
+
|
|
16279
|
+
Relevance scoring has two implementations; pick by output mode:
|
|
16280
|
+
|
|
16281
|
+
- **okf mode** — if `draft/wiki/` exists, use **tree-search retrieval** (`core/shared/okf-retrieval.md`): navigate the OKF Concept Map by reasoning over each concept's routing `description`, descending only the matching subtrees. This is the vectorless, reasoning-based path (PageIndex-style) and supersedes the static section table below for okf bundles.
|
|
16282
|
+
- **monolith mode** — if `draft/wiki/` does not exist, use the static **Scoring Procedure** below against `.ai-context.md` sections.
|
|
16283
|
+
|
|
16284
|
+
The minimum context floor (`META`, `INVARIANTS`, `TEST`, `FILES`) applies to both paths.
|
|
16285
|
+
|
|
16273
16286
|
### Scoring Procedure
|
|
16274
16287
|
|
|
16275
16288
|
1. **Extract key concepts** from the active task:
|
|
@@ -17643,6 +17656,109 @@ The engine indexes C/C++, Go, Python, TypeScript/JS, and more (tree-sitter, 159
|
|
|
17643
17656
|
|
|
17644
17657
|
---
|
|
17645
17658
|
|
|
17659
|
+
## core/shared/okf-retrieval.md
|
|
17660
|
+
|
|
17661
|
+
<core-file path="core/shared/okf-retrieval.md">
|
|
17662
|
+
|
|
17663
|
+
# OKF Tree-Search Retrieval
|
|
17664
|
+
|
|
17665
|
+
Reasoning-based retrieval over the OKF knowledge bundle. When a project was emitted in `okf` mode (`draft/wiki/` exists), agents locate relevant context by **navigating the concept tree** — reading routing descriptions and descending only the matching subtrees — instead of loading sections by a static heuristic. No embeddings, no chunking, no similarity search: relevance is decided by reasoning over the tree, the same way a human expert scans a table of contents.
|
|
17666
|
+
|
|
17667
|
+
Referenced by: `core/shared/draft-context-loading.md` (Relevance-Scored Context Loading). Applies to every command that loads focused project context (`draft implement`, `draft bughunt`, `draft review`, `draft debug`, `draft change`).
|
|
17668
|
+
|
|
17669
|
+
> **Prior art.** This adapts the navigation model of [PageIndex](https://github.com/VectifyAI/PageIndex) (vectorless, reasoning-based RAG) to Draft's self-authored artifacts. Draft already builds the tree — the OKF bundle (`index.md` → section indexes → concept pages) is a table-of-contents whose `description` frontmatter is the per-node routing key. What this procedure adds is the **retrieval loop**: a reasoning descent over that tree. Draft does not need PageIndex's tree-*generation* engine (it authors the tree itself) and stays vectorless by design.
|
|
17670
|
+
|
|
17671
|
+
## When this applies
|
|
17672
|
+
|
|
17673
|
+
Apply tree-search retrieval when ALL of these hold:
|
|
17674
|
+
|
|
17675
|
+
1. `draft/wiki/` exists (project emitted in `okf` mode) **and** `draft/wiki/index.md` carries a populated `<!-- CONCEPT-MAP:START -->…:END -->` block.
|
|
17676
|
+
2. A specific track or task is active (focused retrieval — broad tasks terminate at the Synopsis, see below).
|
|
17677
|
+
3. The command benefits from focused context (the relevance-scoring conditions in `draft-context-loading.md`).
|
|
17678
|
+
|
|
17679
|
+
If `draft/wiki/` does **not** exist (monolith mode), skip this procedure entirely and use the static section-scoring table in `draft-context-loading.md`. The two are mutually exclusive: tree-search is the okf-mode retrieval path; section-scoring is the monolith path.
|
|
17680
|
+
|
|
17681
|
+
## The retrieval loop
|
|
17682
|
+
|
|
17683
|
+
The bundle is a tree: `.ai-context.md` (index root: Synopsis + Concept Map) → section indexes (`systems/`, `features/`, `reference/`, `entrypoints/`, `overview/`) → concept pages. Each node advertises a `description` routing key. Navigate it, do not flatten it.
|
|
17684
|
+
|
|
17685
|
+
```
|
|
17686
|
+
1. Frame the query
|
|
17687
|
+
Extract routing terms from the active task: domain nouns from spec.md
|
|
17688
|
+
acceptance criteria, file paths / module names / tech terms from plan.md,
|
|
17689
|
+
and the primary concern (data flow, API, security, perf, config, …).
|
|
17690
|
+
|
|
17691
|
+
2. Enter at the root
|
|
17692
|
+
Read draft/.ai-context.md. The Synopsis is the cheap broad-context path —
|
|
17693
|
+
for a BROAD task (onboarding, architecture overview, "how does X work
|
|
17694
|
+
end-to-end") it is sufficient: TERMINATE here, do not descend.
|
|
17695
|
+
For a FOCUSED task, read the Concept Map (the root routing table).
|
|
17696
|
+
|
|
17697
|
+
3. Select subtrees (reason, don't match strings)
|
|
17698
|
+
For each Concept Map row, judge the `description` as a ROUTING DECISION:
|
|
17699
|
+
"does opening this concept help THIS task?" Score each candidate:
|
|
17700
|
+
- strong — description names the task's responsibility or its own terms
|
|
17701
|
+
- possible — adjacent/depends-on the task area
|
|
17702
|
+
- skip — unrelated
|
|
17703
|
+
Descend `strong` first; hold `possible` as a frontier for step 5.
|
|
17704
|
+
|
|
17705
|
+
4. Descend to leaves
|
|
17706
|
+
For a selected section, open its index.md and repeat step 3 against the
|
|
17707
|
+
section's concept rows (one routing description per concept). Open the
|
|
17708
|
+
matching concept page(s). A concept page is a LEAF — its `x-grounded-paths`
|
|
17709
|
+
are the exact source files the task should open; `Used by` / `x-callers`
|
|
17710
|
+
give the next hop if the task spans callers.
|
|
17711
|
+
|
|
17712
|
+
5. Expand only if under-covered
|
|
17713
|
+
If the opened leaves do not cover the task's routing terms, expand the
|
|
17714
|
+
highest-scored `possible` frontier node (step 3) and recurse. Otherwise stop.
|
|
17715
|
+
```
|
|
17716
|
+
|
|
17717
|
+
## Routing decision criteria
|
|
17718
|
+
|
|
17719
|
+
The `description` frontmatter is load-bearing — it is written as a routing decision, not a summary (`core/templates/okf/concept.md`). Judge each node by:
|
|
17720
|
+
|
|
17721
|
+
| Signal | Descend when… |
|
|
17722
|
+
|--------|---------------|
|
|
17723
|
+
| Responsibility match | The description names the capability/module the task changes |
|
|
17724
|
+
| Term overlap | Task's domain nouns / file paths appear in the description or `x-grounded-paths` |
|
|
17725
|
+
| Caller/blast-radius reach | Task modifies a symbol whose `x-callers` / `Used by` point at this node |
|
|
17726
|
+
| Concern alignment | Task's primary concern (security, perf, data flow) is this node's stated focus |
|
|
17727
|
+
|
|
17728
|
+
Reason about relevance — do not keyword-match. A concept whose description does not justify opening it for the task at hand is skipped even if a term coincidentally overlaps (similarity ≠ relevance).
|
|
17729
|
+
|
|
17730
|
+
## Termination & budget
|
|
17731
|
+
|
|
17732
|
+
- **Broad task** → terminate at the Synopsis (step 2). Do not open concept pages.
|
|
17733
|
+
- **Focused task** → terminate when opened leaves cover the task's routing terms, or when **≤ 5 concept pages** have been opened (default budget; raise only if the task explicitly spans many subsystems, e.g. a cross-cutting refactor).
|
|
17734
|
+
- **Depth** → the tree is shallow by construction (root → section → concept ≈ 2 hops). If a descent has not reached a leaf in 3 hops, stop and open the best leaf seen so far.
|
|
17735
|
+
- **No match** → if no Concept Map row scores above `skip`, fall back to the Synopsis plus `## INVARIANTS` / `## FILES` / `## TEST` floor from `draft-context-loading.md`.
|
|
17736
|
+
|
|
17737
|
+
The minimum context floor from `draft-context-loading.md` (`META`, `INVARIANTS`, `TEST`, `FILES`) still applies and is always loaded regardless of the descent.
|
|
17738
|
+
|
|
17739
|
+
## Output contract (traceability)
|
|
17740
|
+
|
|
17741
|
+
Tree-search retrieval is explainable by construction — record the path taken, mirroring PageIndex's node-ID grounding:
|
|
17742
|
+
|
|
17743
|
+
- **Opened concepts** — the leaf pages selected, each with the one-line reason it was opened.
|
|
17744
|
+
- **Grounded paths** — the union of `x-grounded-paths` across opened leaves: the precise source files the task will read or modify.
|
|
17745
|
+
- **Skipped frontier** — `possible` nodes held but not expanded (so a follow-up task can resume from them).
|
|
17746
|
+
|
|
17747
|
+
Surface this trace when the command reports which context it loaded (e.g. `draft implement` plan preamble, `draft review` scope note). It replaces "loaded sections A, B, C" with "navigated to concepts X, Y because …".
|
|
17748
|
+
|
|
17749
|
+
## Degradation
|
|
17750
|
+
|
|
17751
|
+
| Scenario | Behavior |
|
|
17752
|
+
|----------|----------|
|
|
17753
|
+
| `draft/wiki/` missing | Skip; use monolith section-scoring in `draft-context-loading.md` |
|
|
17754
|
+
| Concept Map markers empty/absent | Fall back to reading `wiki/*/index.md` section tables directly; if those are missing, use the Synopsis + floor |
|
|
17755
|
+
| Routing descriptions thin/uninformative | Open the section `index.md` and skim concept titles; flag for `draft init refresh` to regenerate descriptions |
|
|
17756
|
+
| Task is broad | Terminate at Synopsis — descending is over-fetch (a Red Flag per `red-flags.md`) |
|
|
17757
|
+
|
|
17758
|
+
</core-file>
|
|
17759
|
+
|
|
17760
|
+
---
|
|
17761
|
+
|
|
17646
17762
|
## core/shared/parallel-analysis.md
|
|
17647
17763
|
|
|
17648
17764
|
<core-file path="core/shared/parallel-analysis.md">
|
package/package.json
CHANGED
package/scripts/lib.sh
CHANGED
package/skills/init/SKILL.md
CHANGED
|
@@ -335,7 +335,11 @@ If the user runs `/draft:init refresh`:
|
|
|
335
335
|
|
|
336
336
|
1. **Tech Stack Refresh**: Re-scan `package.json`, `go.mod`, etc. Compare with `draft/tech-stack.md`. Propose updates.
|
|
337
337
|
|
|
338
|
-
2. **Architecture Refresh**:
|
|
338
|
+
2. **Architecture Refresh**:
|
|
339
|
+
|
|
340
|
+
**Mode detection (do this first).** If `draft/wiki/` exists, the bundle was generated in **`okf` mode** and `architecture.md` is a *generated rendered view*, not the source of truth. In that case **follow `references/okf-emitter.md` §"Incremental refresh at concept granularity (M5)"** instead of the monolith steps below: diff `hashes.json` → map changed source paths to affected concepts → regenerate only those concepts (carry the rest forward from cache) → always re-render `.ai-context.md`, `architecture.md`, and `log.md` via `okf-render-views.sh` → re-run `okf-validate.sh` so cross-links still resolve. Do **not** hand-edit `architecture.md` in this mode — it is overwritten by the renderer. Then skip to step 3.
|
|
341
|
+
|
|
342
|
+
Otherwise (**`monolith` mode** — `draft/architecture.md` is the source of truth and no `draft/wiki/` exists), use metadata-based incremental analysis. If freshness state is available from step 0b, use file-level deltas to scope the refresh more precisely than git-diff alone:
|
|
339
343
|
|
|
340
344
|
**a. Read synced commit from metadata:**
|
|
341
345
|
```bash
|