context-loader 1.3.5__tar.gz → 1.3.6__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: context-loader
3
- Version: 1.3.5
3
+ Version: 1.3.6
4
4
  Summary: Render deterministic local Git context for any executor
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -219,14 +219,14 @@ Python standard library.
219
219
 
220
220
  ## Open-source quick start
221
221
 
222
- Current stable release: **1.3.5**. Local CLI for coding-agent workflows; renders deterministic Markdown or JSON.
222
+ Current stable release: **1.3.6**. Local CLI for coding-agent workflows; renders deterministic Markdown or JSON.
223
223
 
224
224
  ```bash
225
- uv tool install 'context-loader==1.3.5'
225
+ uv tool install 'context-loader==1.3.6'
226
226
  ```
227
227
 
228
228
  ```bash
229
- pip install 'context-loader==1.3.5'
229
+ pip install 'context-loader==1.3.6'
230
230
  ```
231
231
 
232
232
  ```bash
@@ -239,21 +239,21 @@ project-context --repo /path/to/repo --format json
239
239
 
240
240
  ## Install
241
241
 
242
- Source version: `1.3.5`. Install its matching published release or an exact source commit.
242
+ Source version: `1.3.6`. Install its matching published release or an exact source commit.
243
243
 
244
244
  Install via `uv`:
245
245
 
246
246
  ```bash
247
- uv tool install 'context-loader==1.3.5'
247
+ uv tool install 'context-loader==1.3.6'
248
248
  ```
249
249
 
250
250
  Install via `pip`:
251
251
 
252
252
  ```bash
253
- pip install 'context-loader==1.3.5'
253
+ pip install 'context-loader==1.3.6'
254
254
  ```
255
255
 
256
- For development or source-based installs tracking current repository (`1.3.5`):
256
+ For development or source-based installs tracking current repository (`1.3.6`):
257
257
 
258
258
  ```bash
259
259
  uv tool install git+https://github.com/xuanheng-tech/context-loader.git
@@ -350,7 +350,7 @@ set differs, as described under “Compact model consumption”. The declared co
350
350
  "schema_version": 3,
351
351
  "tool": {
352
352
  "name": "context-loader",
353
- "version": "1.3.5"
353
+ "version": "1.3.6"
354
354
  },
355
355
  "repository": {
356
356
  "requested_path": "/canonical/requested/path",
@@ -470,7 +470,7 @@ although 1.1.0 added the top-level `statuses` key. From release 1.2.0 onward eac
470
470
  names exactly one key set, and a new number is issued whenever a key set would otherwise be reused.
471
471
 
472
472
  The JSON schema version and package version are independent: this build emits `schema_version` `3`
473
- for `--format json` and `4` for `--format json-compact`, while `tool.version` is `1.3.5`. Version 1
473
+ for `--format json` and `4` for `--format json-compact`, while `tool.version` is `1.3.6`. Version 1
474
474
  and 2 are the exact shapes already published in release 1.2.0 and are never reused: because
475
475
  `nested_context` changes the default document's key set, version 3 names the current full-document
476
476
  key set and version 4 names the compact projection.
@@ -512,12 +512,20 @@ heading on the first line is still recognized as a heading.
512
512
 
513
513
  The root `AGENTS.md` is split at Markdown headings outside fenced code blocks. The output always
514
514
  starts with complete early sections fitting a 4-KiB head, then adds complete relevant sections in
515
- source order using exact normalized focus/path tokens and their parent context. Remaining headings
515
+ source order using normalized focus/path tokens and their parent context. Remaining headings
516
516
  appear in an explicit index whose body text is not loaded. With no selection signals, only the small
517
517
  head and index are emitted. Unsafe heading parsing falls back to a bounded head and an explicit
518
518
  manual-recovery notice. A head whose own headings would not fit the budget falls back to the same
519
519
  bounded head without a section index; a single instruction file never fails the whole collection.
520
520
 
521
+ Matching uses NFKC normalization and case folding. Ordinary tokens require at least three characters;
522
+ two-character Han terms such as `安全` and `部署`, and the technical abbreviations `AI`, `CD`, `CI`,
523
+ `DB`, `IO`, `JS`, `ML`, `OS`, `PR`, `QA`, `TS`, `UI` and `UX`, are also eligible. Han terms can match
524
+ within entirely Han words, so `安全` matches `安全规则`; Latin terms still require complete tokens,
525
+ so `CI` does not match `special`. Existing stopwords, scoring and byte budgets still apply. Repeating
526
+ a Han term in a heading and body does not increase its score. This is literal matching without word
527
+ segmentation, synonyms or translation.
528
+
521
529
  `Omitted source characters` is measured against the whole normalized source, so a bounded source
522
530
  scan that ends before EOF still reports the characters it could not select.
523
531
 
@@ -647,7 +655,7 @@ or candidate-file content.
647
655
 
648
656
  ## Not Included
649
657
 
650
- Version 1.3.5 does not provide AI summaries, project-type detection, loading or transport of
658
+ Version 1.3.6 does not provide AI summaries, project-type detection, loading or transport of
651
659
  nested `AGENTS.md` contents (the JSON `nested_context` field reports bounded existence only),
652
660
  Memory retrieval, semantic ranking, ignore-rule parsing, plugins, profiles, caches, databases,
653
661
  network services, MCP, daemons, GUIs, CI/CD, telemetry, or automatic updates.
@@ -8,14 +8,14 @@ Python standard library.
8
8
 
9
9
  ## Open-source quick start
10
10
 
11
- Current stable release: **1.3.5**. Local CLI for coding-agent workflows; renders deterministic Markdown or JSON.
11
+ Current stable release: **1.3.6**. Local CLI for coding-agent workflows; renders deterministic Markdown or JSON.
12
12
 
13
13
  ```bash
14
- uv tool install 'context-loader==1.3.5'
14
+ uv tool install 'context-loader==1.3.6'
15
15
  ```
16
16
 
17
17
  ```bash
18
- pip install 'context-loader==1.3.5'
18
+ pip install 'context-loader==1.3.6'
19
19
  ```
20
20
 
21
21
  ```bash
@@ -28,21 +28,21 @@ project-context --repo /path/to/repo --format json
28
28
 
29
29
  ## Install
30
30
 
31
- Source version: `1.3.5`. Install its matching published release or an exact source commit.
31
+ Source version: `1.3.6`. Install its matching published release or an exact source commit.
32
32
 
33
33
  Install via `uv`:
34
34
 
35
35
  ```bash
36
- uv tool install 'context-loader==1.3.5'
36
+ uv tool install 'context-loader==1.3.6'
37
37
  ```
38
38
 
39
39
  Install via `pip`:
40
40
 
41
41
  ```bash
42
- pip install 'context-loader==1.3.5'
42
+ pip install 'context-loader==1.3.6'
43
43
  ```
44
44
 
45
- For development or source-based installs tracking current repository (`1.3.5`):
45
+ For development or source-based installs tracking current repository (`1.3.6`):
46
46
 
47
47
  ```bash
48
48
  uv tool install git+https://github.com/xuanheng-tech/context-loader.git
@@ -139,7 +139,7 @@ set differs, as described under “Compact model consumption”. The declared co
139
139
  "schema_version": 3,
140
140
  "tool": {
141
141
  "name": "context-loader",
142
- "version": "1.3.5"
142
+ "version": "1.3.6"
143
143
  },
144
144
  "repository": {
145
145
  "requested_path": "/canonical/requested/path",
@@ -259,7 +259,7 @@ although 1.1.0 added the top-level `statuses` key. From release 1.2.0 onward eac
259
259
  names exactly one key set, and a new number is issued whenever a key set would otherwise be reused.
260
260
 
261
261
  The JSON schema version and package version are independent: this build emits `schema_version` `3`
262
- for `--format json` and `4` for `--format json-compact`, while `tool.version` is `1.3.5`. Version 1
262
+ for `--format json` and `4` for `--format json-compact`, while `tool.version` is `1.3.6`. Version 1
263
263
  and 2 are the exact shapes already published in release 1.2.0 and are never reused: because
264
264
  `nested_context` changes the default document's key set, version 3 names the current full-document
265
265
  key set and version 4 names the compact projection.
@@ -301,12 +301,20 @@ heading on the first line is still recognized as a heading.
301
301
 
302
302
  The root `AGENTS.md` is split at Markdown headings outside fenced code blocks. The output always
303
303
  starts with complete early sections fitting a 4-KiB head, then adds complete relevant sections in
304
- source order using exact normalized focus/path tokens and their parent context. Remaining headings
304
+ source order using normalized focus/path tokens and their parent context. Remaining headings
305
305
  appear in an explicit index whose body text is not loaded. With no selection signals, only the small
306
306
  head and index are emitted. Unsafe heading parsing falls back to a bounded head and an explicit
307
307
  manual-recovery notice. A head whose own headings would not fit the budget falls back to the same
308
308
  bounded head without a section index; a single instruction file never fails the whole collection.
309
309
 
310
+ Matching uses NFKC normalization and case folding. Ordinary tokens require at least three characters;
311
+ two-character Han terms such as `安全` and `部署`, and the technical abbreviations `AI`, `CD`, `CI`,
312
+ `DB`, `IO`, `JS`, `ML`, `OS`, `PR`, `QA`, `TS`, `UI` and `UX`, are also eligible. Han terms can match
313
+ within entirely Han words, so `安全` matches `安全规则`; Latin terms still require complete tokens,
314
+ so `CI` does not match `special`. Existing stopwords, scoring and byte budgets still apply. Repeating
315
+ a Han term in a heading and body does not increase its score. This is literal matching without word
316
+ segmentation, synonyms or translation.
317
+
310
318
  `Omitted source characters` is measured against the whole normalized source, so a bounded source
311
319
  scan that ends before EOF still reports the characters it could not select.
312
320
 
@@ -436,7 +444,7 @@ or candidate-file content.
436
444
 
437
445
  ## Not Included
438
446
 
439
- Version 1.3.5 does not provide AI summaries, project-type detection, loading or transport of
447
+ Version 1.3.6 does not provide AI summaries, project-type detection, loading or transport of
440
448
  nested `AGENTS.md` contents (the JSON `nested_context` field reports bounded existence only),
441
449
  Memory retrieval, semantic ranking, ignore-rule parsing, plugins, profiles, caches, databases,
442
450
  network services, MCP, daemons, GUIs, CI/CD, telemetry, or automatic updates.
@@ -1,3 +1,3 @@
1
1
  """Project Context Loader."""
2
2
 
3
- __version__ = "1.3.5"
3
+ __version__ = "1.3.6"
@@ -68,6 +68,9 @@ _MAKE_TARGET_RE = re.compile(
68
68
  )
69
69
  _ATX_HEADING_RE = re.compile(r"^ {0,3}(#{1,6})(?:[ \t]+(.*)|[ \t]*)$")
70
70
  _TOKEN_RE = re.compile(r"[^\W_]+", re.UNICODE)
71
+ _SHORT_TECHNICAL_TOKENS = frozenset(
72
+ {"ai", "cd", "ci", "db", "io", "js", "ml", "os", "pr", "qa", "ts", "ui", "ux"}
73
+ )
71
74
  _MATCH_TOKEN_STOPWORDS = frozenset(
72
75
  {
73
76
  "and",
@@ -138,11 +141,35 @@ def _normalized_text(value: str) -> str:
138
141
  return unicodedata.normalize("NFKC", value).casefold()
139
142
 
140
143
 
144
+ def _is_han_token(value: str) -> bool:
145
+ return bool(value) and all(
146
+ unicodedata.name(character, "").startswith("CJK UNIFIED IDEOGRAPH-") for character in value
147
+ )
148
+
149
+
141
150
  def _matching_tokens(value: str, stopwords: frozenset[str]) -> frozenset[str]:
142
151
  return frozenset(
143
152
  token
144
153
  for token in _TOKEN_RE.findall(_normalized_text(value))
145
- if len(token) >= 3 and token not in stopwords
154
+ if token not in stopwords
155
+ and (
156
+ len(token) >= 3
157
+ or token in _SHORT_TECHNICAL_TOKENS
158
+ or (len(token) == 2 and _is_han_token(token))
159
+ )
160
+ )
161
+
162
+
163
+ def _matched_terms(terms: frozenset[str], tokens: frozenset[str]) -> frozenset[str]:
164
+ matches = terms & tokens
165
+ han_terms = tuple(term for term in terms - matches if _is_han_token(term))
166
+ if not han_terms:
167
+ return matches
168
+ # Han text need not delimit words with spaces. Count each query term once,
169
+ # without introducing substring matching for Latin words or abbreviations.
170
+ han_tokens = tuple(token for token in tokens if _is_han_token(token))
171
+ return matches | frozenset(
172
+ term for term in han_terms if any(term in token for token in han_tokens)
146
173
  )
147
174
 
148
175
 
@@ -334,24 +361,20 @@ def _small_head_end(content: str, sections: tuple[MarkdownSection, ...]) -> int:
334
361
  def _section_relevance(
335
362
  section: MarkdownSection, signals: _SelectionSignals
336
363
  ) -> tuple[int, frozenset[str]]:
337
- heading_tokens = frozenset(
338
- token
339
- for token in section.normalized_heading.split()
340
- if len(token) >= 3 and token not in _MATCH_TOKEN_STOPWORDS
341
- )
364
+ heading_tokens = _matching_tokens(section.normalized_heading, _MATCH_TOKEN_STOPWORDS)
342
365
  section_tokens = _matching_tokens(section.text, _MATCH_TOKEN_STOPWORDS)
343
366
  body_tokens = section_tokens - heading_tokens
344
367
  score = 0
345
368
  reasons: set[str] = set()
346
369
 
347
- focus_heading = signals.focus_tokens & heading_tokens
348
- focus_body = signals.focus_tokens & body_tokens
370
+ focus_heading = _matched_terms(signals.focus_tokens, heading_tokens)
371
+ focus_body = _matched_terms(signals.focus_tokens, body_tokens) - focus_heading
349
372
  if focus_heading or focus_body:
350
373
  reasons.add("focus_match")
351
374
  score += 6 * len(focus_heading) + len(focus_body)
352
375
 
353
- path_heading = signals.path_tokens & heading_tokens
354
- path_body = signals.path_tokens & body_tokens
376
+ path_heading = _matched_terms(signals.path_tokens, heading_tokens)
377
+ path_body = _matched_terms(signals.path_tokens, body_tokens) - path_heading
355
378
  exact_path = bool(
356
379
  signals.normalized_path
357
380
  and _normalized_text(signals.normalized_path) in _normalized_text(section.text)
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "context-loader"
7
- version = "1.3.5"
7
+ version = "1.3.6"
8
8
  description = "Render deterministic local Git context for any executor"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12,<3.15"
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "context-loader"
7
- version = "1.3.5"
7
+ version = "1.3.6"
8
8
  description = "Render deterministic local Git context for any executor"
9
9
  license = { file = "LICENSE" }
10
10
  readme = "README.md"
@@ -46,5 +46,5 @@
46
46
  ],
47
47
  "schema_version": 1,
48
48
  "tool_name": "context-loader",
49
- "tool_version": "1.3.5"
49
+ "tool_version": "1.3.6"
50
50
  }
File without changes