@drafthq/draft 3.5.2 → 3.5.3

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.
@@ -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.5.2",
15
+ "version": "3.5.3",
16
16
  "author": {
17
17
  "name": "mayurpise"
18
18
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "draft",
3
3
  "description": "Context-Driven Development: draft specs and plans before implementation. Structured workflows for features and fixes.",
4
- "version": "3.5.2",
4
+ "version": "3.5.3",
5
5
  "author": {
6
6
  "name": "mayurpise"
7
7
  },
@@ -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.2",
5
+ "version": "3.5.3",
6
6
  "skills": "./skills/",
7
7
  "agents": "./core/agents/",
8
8
  "author": {
@@ -1,17 +1,13 @@
1
1
  ---
2
- type: Subsystem
3
- title: "{PROJECT_NAME} — Wiki"
4
- description: >
5
- Root index of the project wiki. Start here, then route into
6
- overview/, systems/, features/, reference/, or entrypoints/ via the
7
- Concept Map. Open a concept only when its description matches the task.
8
- resource: .
9
- tags: [index]
10
- timestamp: "{ISO_TIMESTAMP}"
11
2
  okf_version: "0.1"
12
- okf_types_version: "0.1"
13
3
  ---
14
4
 
5
+ <!-- OKF §6/§11: an index file carries NO concept frontmatter; the root index.md
6
+ may declare ONLY `okf_version`. The frozen concept-`type` vocabulary version
7
+ is tracked here in the body (not in frontmatter) so bumping it stays visible
8
+ without violating the index-frontmatter rule.
9
+ okf-types-version: 0.1 -->
10
+
15
11
  # {PROJECT_NAME} — Wiki
16
12
 
17
13
  > Project wiki. One concept per file; cross-links form the graph. The
@@ -1,14 +1,5 @@
1
- ---
2
- type: Subsystem
3
- title: "{SECTION_TITLE}"
4
- description: >
5
- Section index. Lists every concept in this section with its one-line
6
- routing description so an agent can pick the right page without opening
7
- each one. {SECTION_PURPOSE}
8
- resource: .
9
- tags: [index]
10
- timestamp: "{ISO_TIMESTAMP}"
11
- ---
1
+ <!-- OKF §6: an index file contains NO frontmatter. This page is a reserved
2
+ navigation index, not a concept — its Concepts table is tool-generated. -->
12
3
 
13
4
  # {SECTION_TITLE}
14
5
 
@@ -3353,7 +3353,8 @@ Templates for each bundle page live in `core/templates/okf/` (`index.md`,
3353
3353
  ## Frozen `type` vocabulary
3354
3354
 
3355
3355
  Every concept carries a `type` from this frozen set (changing it churns every
3356
- file; versioned via `index.md` frontmatter `okf_types_version`):
3356
+ file; versioned via the `okf-types-version` comment in the wiki root `index.md`
3357
+ body — OKF §6/§11 permit only `okf_version` in an index file's frontmatter):
3357
3358
 
3358
3359
  | type | Maps to | Home |
3359
3360
  |------|---------|------|
@@ -3379,6 +3380,16 @@ the task at hand?"), never a summary. Draft extensions are namespaced `x-` and
3379
3380
  ignored by generic OKF consumers: `x-grounded-paths`, `x-hotspot-score`,
3380
3381
  `x-callers`.
3381
3382
 
3383
+ **Meta pages are not concepts.** Index files (`wiki/index.md` and every
3384
+ `<section>/index.md`) carry **no concept frontmatter**: per OKF §6 an index file
3385
+ has no frontmatter, and per §11 the root `index.md` may declare **only**
3386
+ `okf_version`. The tool-generated `systems/coverage.md` is a non-reserved file, so
3387
+ OKF §9.1/§9.2 require it to carry a typed frontmatter block; it uses a descriptive
3388
+ `type: Report` and is exempt from the frozen vocabulary via `is_meta_page`
3389
+ (basename + the `<!-- okf:coverage-generated -->` marker). `okf-validate.sh`
3390
+ short-circuits all meta pages before the concept checks, so they are never
3391
+ vocab-checked or counted as concepts.
3392
+
3382
3393
  ## Concept granularity (resolves open decision 1)
3383
3394
 
3384
3395
  Derive concepts from the graph, not by hand:
@@ -22653,19 +22664,15 @@ List down alerting thresholds on those metrics:
22653
22664
  <core-file path="core/templates/okf/index.md">
22654
22665
 
22655
22666
  ---
22656
- type: Subsystem
22657
- title: "{PROJECT_NAME} — Wiki"
22658
- description: >
22659
- Root index of the project wiki. Start here, then route into
22660
- overview/, systems/, features/, reference/, or entrypoints/ via the
22661
- Concept Map. Open a concept only when its description matches the task.
22662
- resource: .
22663
- tags: [index]
22664
- timestamp: "{ISO_TIMESTAMP}"
22665
22667
  okf_version: "0.1"
22666
- okf_types_version: "0.1"
22667
22668
  ---
22668
22669
 
22670
+ <!-- OKF §6/§11: an index file carries NO concept frontmatter; the root index.md
22671
+ may declare ONLY `okf_version`. The frozen concept-`type` vocabulary version
22672
+ is tracked here in the body (not in frontmatter) so bumping it stays visible
22673
+ without violating the index-frontmatter rule.
22674
+ okf-types-version: 0.1 -->
22675
+
22669
22676
  # {PROJECT_NAME} — Wiki
22670
22677
 
22671
22678
  > Project wiki. One concept per file; cross-links form the graph. The
@@ -22773,17 +22780,8 @@ Entrypoint) require ≥1 valid Mermaid block and ≥2 x-grounded-paths.
22773
22780
 
22774
22781
  <core-file path="core/templates/okf/section-index.md">
22775
22782
 
22776
- ---
22777
- type: Subsystem
22778
- title: "{SECTION_TITLE}"
22779
- description: >
22780
- Section index. Lists every concept in this section with its one-line
22781
- routing description so an agent can pick the right page without opening
22782
- each one. {SECTION_PURPOSE}
22783
- resource: .
22784
- tags: [index]
22785
- timestamp: "{ISO_TIMESTAMP}"
22786
- ---
22783
+ <!-- OKF §6: an index file contains NO frontmatter. This page is a reserved
22784
+ navigation index, not a concept — its Concepts table is tool-generated. -->
22787
22785
 
22788
22786
  # {SECTION_TITLE}
22789
22787
 
@@ -3353,7 +3353,8 @@ Templates for each bundle page live in `core/templates/okf/` (`index.md`,
3353
3353
  ## Frozen `type` vocabulary
3354
3354
 
3355
3355
  Every concept carries a `type` from this frozen set (changing it churns every
3356
- file; versioned via `index.md` frontmatter `okf_types_version`):
3356
+ file; versioned via the `okf-types-version` comment in the wiki root `index.md`
3357
+ body — OKF §6/§11 permit only `okf_version` in an index file's frontmatter):
3357
3358
 
3358
3359
  | type | Maps to | Home |
3359
3360
  |------|---------|------|
@@ -3379,6 +3380,16 @@ the task at hand?"), never a summary. Draft extensions are namespaced `x-` and
3379
3380
  ignored by generic OKF consumers: `x-grounded-paths`, `x-hotspot-score`,
3380
3381
  `x-callers`.
3381
3382
 
3383
+ **Meta pages are not concepts.** Index files (`wiki/index.md` and every
3384
+ `<section>/index.md`) carry **no concept frontmatter**: per OKF §6 an index file
3385
+ has no frontmatter, and per §11 the root `index.md` may declare **only**
3386
+ `okf_version`. The tool-generated `systems/coverage.md` is a non-reserved file, so
3387
+ OKF §9.1/§9.2 require it to carry a typed frontmatter block; it uses a descriptive
3388
+ `type: Report` and is exempt from the frozen vocabulary via `is_meta_page`
3389
+ (basename + the `<!-- okf:coverage-generated -->` marker). `okf-validate.sh`
3390
+ short-circuits all meta pages before the concept checks, so they are never
3391
+ vocab-checked or counted as concepts.
3392
+
3382
3393
  ## Concept granularity (resolves open decision 1)
3383
3394
 
3384
3395
  Derive concepts from the graph, not by hand:
@@ -22653,19 +22664,15 @@ List down alerting thresholds on those metrics:
22653
22664
  <core-file path="core/templates/okf/index.md">
22654
22665
 
22655
22666
  ---
22656
- type: Subsystem
22657
- title: "{PROJECT_NAME} — Wiki"
22658
- description: >
22659
- Root index of the project wiki. Start here, then route into
22660
- overview/, systems/, features/, reference/, or entrypoints/ via the
22661
- Concept Map. Open a concept only when its description matches the task.
22662
- resource: .
22663
- tags: [index]
22664
- timestamp: "{ISO_TIMESTAMP}"
22665
22667
  okf_version: "0.1"
22666
- okf_types_version: "0.1"
22667
22668
  ---
22668
22669
 
22670
+ <!-- OKF §6/§11: an index file carries NO concept frontmatter; the root index.md
22671
+ may declare ONLY `okf_version`. The frozen concept-`type` vocabulary version
22672
+ is tracked here in the body (not in frontmatter) so bumping it stays visible
22673
+ without violating the index-frontmatter rule.
22674
+ okf-types-version: 0.1 -->
22675
+
22669
22676
  # {PROJECT_NAME} — Wiki
22670
22677
 
22671
22678
  > Project wiki. One concept per file; cross-links form the graph. The
@@ -22773,17 +22780,8 @@ Entrypoint) require ≥1 valid Mermaid block and ≥2 x-grounded-paths.
22773
22780
 
22774
22781
  <core-file path="core/templates/okf/section-index.md">
22775
22782
 
22776
- ---
22777
- type: Subsystem
22778
- title: "{SECTION_TITLE}"
22779
- description: >
22780
- Section index. Lists every concept in this section with its one-line
22781
- routing description so an agent can pick the right page without opening
22782
- each one. {SECTION_PURPOSE}
22783
- resource: .
22784
- tags: [index]
22785
- timestamp: "{ISO_TIMESTAMP}"
22786
- ---
22783
+ <!-- OKF §6: an index file contains NO frontmatter. This page is a reserved
22784
+ navigation index, not a concept — its Concepts table is tool-generated. -->
22787
22785
 
22788
22786
  # {SECTION_TITLE}
22789
22787
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drafthq/draft",
3
- "version": "3.5.2",
3
+ "version": "3.5.3",
4
4
  "description": "Context-Driven Development for AI coding agents — install Draft into Claude Code, Cursor, Codex, or opencode.",
5
5
  "bin": {
6
6
  "draft": "cli/bin/draft.js"
@@ -122,6 +122,17 @@ write_coverage_page() {
122
122
  mkdir -p "$BUNDLE/systems"
123
123
  local tmp; tmp="$(mktemp)"
124
124
  {
125
+ # OKF §9.1/§9.2: every non-reserved .md needs parseable frontmatter with a
126
+ # non-empty `type`. coverage.md is tool-generated and not a code concept, so
127
+ # it uses a descriptive (non-frozen) type; okf-validate.sh exempts it from the
128
+ # frozen-vocab check via is_meta_page (basename + the marker below).
129
+ echo "---"
130
+ echo "type: Report"
131
+ echo "title: Component Coverage"
132
+ echo "description: Coverage of required components by wiki pages — which are documented, stubbed, or missing."
133
+ echo "resource: ."
134
+ echo "---"
135
+ echo ""
125
136
  echo "<!-- okf:coverage-generated -->"
126
137
  echo "# Component Coverage"
127
138
  echo ""
@@ -130,14 +141,21 @@ write_coverage_page() {
130
141
  echo ""
131
142
  echo "| Component | Wiki page | Status | Fan-in |"
132
143
  echo "|-----------|-----------|--------|--------|"
133
- local cid status fanin
144
+ local cid status fanin link
134
145
  while IFS=$'\t' read -r cid required reason ftype fanin; do
135
146
  [[ -z "$cid" ]] && continue
136
147
  if [[ "$required" == "true" ]]; then
137
148
  if [[ -f "$BUNDLE/$cid" ]]; then
138
149
  bl="$(body_lines "$BUNDLE/$cid")"
150
+ # coverage.md lives in systems/; link relative to it. Concepts in
151
+ # other sections (entrypoints/, reference/, …) need a ../ prefix,
152
+ # otherwise the link dangles and fails structure validation.
153
+ case "$cid" in
154
+ systems/*) link="${cid#systems/}";;
155
+ *) link="../$cid";;
156
+ esac
139
157
  if [[ "$bl" -ge "$MIN_STUB_LINES" ]]; then
140
- echo "| \`${cid%.md}\` | [page](${cid#systems/}) | Full | ${fanin} |"
158
+ echo "| \`${cid%.md}\` | [page](${link}) | Full | ${fanin} |"
141
159
  else
142
160
  echo "| \`${cid%.md}\` | ${cid} | **STUB (${bl} lines)** | ${fanin} |"
143
161
  fi
@@ -109,6 +109,17 @@ strip_frontmatter() {
109
109
  ' "$1"
110
110
  }
111
111
 
112
+ # Human-facing title for a page: frontmatter `title`, else the first `# H1` in the
113
+ # body, else the bundle-relative path. Index files are frontmatter-less under OKF
114
+ # §6, so the H1 fallback keeps the rendered TOC / nav readable.
115
+ page_title() {
116
+ local t; t="$(get_yaml_field "$1" title)"
117
+ if [[ -z "$t" ]]; then
118
+ t="$(strip_frontmatter "$1" | grep -m1 -E '^#[[:space:]]+' | sed -E 's/^#[[:space:]]+//')"
119
+ fi
120
+ printf '%s' "$t"
121
+ }
122
+
112
123
  # Coverage-honesty banner, sourced from okf-coverage-check.sh's JSON report.
113
124
  # Silent when no report is supplied (keeps the view backward-compatible).
114
125
  emit_coverage_banner() {
@@ -159,7 +170,7 @@ render_architecture() {
159
170
  echo "- **${sec}/**"
160
171
  last_sec="$sec"
161
172
  fi
162
- title="$(get_yaml_field "$BUNDLE/$rel" title)"
173
+ title="$(page_title "$BUNDLE/$rel")"
163
174
  [[ -n "$title" ]] || title="$rel"
164
175
  local anchor; anchor="$(printf '%s' "$title" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-')"
165
176
  anchor="${anchor#-}"; anchor="${anchor%-}"
@@ -183,10 +194,14 @@ render_architecture() {
183
194
  build_concept_map() {
184
195
  echo "| Concept | Type | Open it when… |"
185
196
  echo "|---------|------|---------------|"
186
- local rel type title desc
197
+ local rel base type title desc
187
198
  while IFS= read -r -d '' page; do
188
199
  rel="${page#"$BUNDLE/"}"
189
- [[ "$(basename "$rel")" == "index.md" ]] && continue
200
+ base="$(basename "$rel")"
201
+ # Meta pages are not routable concepts (reserved index/log + the typed,
202
+ # tool-generated coverage page).
203
+ [[ "$base" == "index.md" || "$base" == "log.md" || "$base" == "coverage.md" ]] && continue
204
+ grep -q '<!-- okf:coverage-generated -->' "$page" 2>/dev/null && continue
190
205
  type="$(get_yaml_field "$page" type)"
191
206
  [[ -n "$type" ]] || continue
192
207
  title="$(get_yaml_field "$page" title)"
@@ -330,7 +345,7 @@ HTML_HEAD
330
345
  while IFS= read -r -d '' page; do
331
346
  local rel title type
332
347
  rel="${page#"$BUNDLE/"}"
333
- title="$(get_yaml_field "$page" title)"; [[ -n "$title" ]] || title="$rel"
348
+ title="$(page_title "$page")"; [[ -n "$title" ]] || title="$rel"
334
349
  type="$(get_yaml_field "$page" type)"
335
350
  printf '%s: {"title": %s, "type": %s, "md": %s},\n' \
336
351
  "$(jq -Rn --arg v "$rel" '$v')" \
@@ -135,18 +135,25 @@ while IFS= read -r -d '' page; do
135
135
  rel="${page#"$BUNDLE/"}"
136
136
  base="$(basename "$rel")"
137
137
 
138
+ # Meta pages are NOT concepts: reserved index.md/log.md (OKF §6/§7) carry no
139
+ # concept frontmatter, and the tool-generated coverage page uses a descriptive
140
+ # (non-frozen) type. Exempt them from the frozen-vocab + required-field + body
141
+ # checks, and don't count them as concepts. The template-token (§3b) and
142
+ # cross-link (§4) scans below still cover them.
143
+ if is_meta_page "$base" "$page"; then
144
+ continue
145
+ fi
146
+
138
147
  type_val="$(get_yaml_field "$page" "type")"
139
148
 
140
149
  # Empty / placeholder pages: a non-meta page with no type (or no body) slips
141
150
  # past every downstream check (quality + coverage both key on `type`). Catch
142
151
  # it here so a blank or stub file can never ship.
143
152
  if [[ -z "$type_val" ]]; then
144
- if ! is_meta_page "$base" "$page"; then
145
- if [[ "$(nonblank_body_lines "$page")" -eq 0 ]]; then
146
- add_error "$rel: empty page (no frontmatter type, no body) — every wiki page must be a real concept"
147
- else
148
- add_error "$rel: untyped page (missing frontmatter 'type:') — not a valid concept page"
149
- fi
153
+ if [[ "$(nonblank_body_lines "$page")" -eq 0 ]]; then
154
+ add_error "$rel: empty page (no frontmatter type, no body) every wiki page must be a real concept"
155
+ else
156
+ add_error "$rel: untyped page (missing frontmatter 'type:') — not a valid concept page"
150
157
  fi
151
158
  continue
152
159
  fi
@@ -77,7 +77,8 @@ Templates for each bundle page live in `core/templates/okf/` (`index.md`,
77
77
  ## Frozen `type` vocabulary
78
78
 
79
79
  Every concept carries a `type` from this frozen set (changing it churns every
80
- file; versioned via `index.md` frontmatter `okf_types_version`):
80
+ file; versioned via the `okf-types-version` comment in the wiki root `index.md`
81
+ body — OKF §6/§11 permit only `okf_version` in an index file's frontmatter):
81
82
 
82
83
  | type | Maps to | Home |
83
84
  |------|---------|------|
@@ -103,6 +104,16 @@ the task at hand?"), never a summary. Draft extensions are namespaced `x-` and
103
104
  ignored by generic OKF consumers: `x-grounded-paths`, `x-hotspot-score`,
104
105
  `x-callers`.
105
106
 
107
+ **Meta pages are not concepts.** Index files (`wiki/index.md` and every
108
+ `<section>/index.md`) carry **no concept frontmatter**: per OKF §6 an index file
109
+ has no frontmatter, and per §11 the root `index.md` may declare **only**
110
+ `okf_version`. The tool-generated `systems/coverage.md` is a non-reserved file, so
111
+ OKF §9.1/§9.2 require it to carry a typed frontmatter block; it uses a descriptive
112
+ `type: Report` and is exempt from the frozen vocabulary via `is_meta_page`
113
+ (basename + the `<!-- okf:coverage-generated -->` marker). `okf-validate.sh`
114
+ short-circuits all meta pages before the concept checks, so they are never
115
+ vocab-checked or counted as concepts.
116
+
106
117
  ## Concept granularity (resolves open decision 1)
107
118
 
108
119
  Derive concepts from the graph, not by hand: