jfox-cli 0.1.3__tar.gz → 0.1.5__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.
Files changed (79) hide show
  1. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/.github/workflows/integration-test.yml +98 -4
  2. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/CLAUDE.md +5 -0
  3. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/PKG-INFO +1 -1
  4. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/__init__.py +1 -1
  5. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/bm25_index.py +181 -105
  6. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/cli.py +746 -432
  7. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/config.py +32 -29
  8. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/embedding_backend.py +10 -11
  9. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/formatters.py +55 -66
  10. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/global_config.py +56 -64
  11. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/graph.py +54 -57
  12. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/indexer.py +114 -95
  13. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/kb_manager.py +62 -67
  14. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/models.py +40 -37
  15. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/note.py +358 -113
  16. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/performance.py +99 -89
  17. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/search_engine.py +65 -52
  18. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/template.py +64 -53
  19. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/template_cli.py +47 -42
  20. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/vector_store.py +76 -51
  21. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/pyproject.toml +4 -2
  22. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skills-recommend/claude-code/jfox-insert/SKILL.md +25 -0
  23. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skills-recommend/claude-code/jfox-organize/SKILL.md +7 -2
  24. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/conftest.py +96 -89
  25. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/integration/test_backlinks.py +35 -51
  26. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/performance/test_performance.py +76 -75
  27. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_advanced_features.py +58 -29
  28. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_cli_format.py +164 -31
  29. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_config_unit.py +74 -70
  30. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_core_workflow.py +140 -129
  31. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_hybrid_search.py +40 -37
  32. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_integration.py +11 -11
  33. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_kb_current.py +18 -20
  34. jfox_cli-0.1.5/tests/unit/test_bm25_batch.py +267 -0
  35. jfox_cli-0.1.5/tests/unit/test_edit.py +386 -0
  36. jfox_cli-0.1.5/tests/unit/test_format_unify.py +319 -0
  37. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/unit/test_formatters.py +35 -24
  38. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/unit/test_global_config.py +157 -174
  39. jfox_cli-0.1.5/tests/unit/test_index_kb_param.py +92 -0
  40. jfox_cli-0.1.5/tests/unit/test_indexer_clear_before_rebuild.py +69 -0
  41. jfox_cli-0.1.5/tests/unit/test_indexer_verify.py +53 -0
  42. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/unit/test_kb_manager.py +114 -127
  43. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/unit/test_template.py +32 -43
  44. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/unit/test_template_cli.py +250 -233
  45. jfox_cli-0.1.5/tests/unit/test_vector_store_clear.py +76 -0
  46. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/utils/assertions.py +45 -32
  47. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/utils/jfox_cli.py +128 -109
  48. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/utils/note_generator.py +44 -51
  49. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/utils/temp_kb.py +5 -5
  50. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/uv.lock +1 -1
  51. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/.githooks/pre-push +0 -0
  52. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/.github/workflows/publish.yml +0 -0
  53. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/.gitignore +0 -0
  54. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/.python-version +0 -0
  55. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/AGENTS.md +0 -0
  56. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/DEVELOPMENT_PLAN.md +0 -0
  57. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/README.md +0 -0
  58. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/SESSION.md +0 -0
  59. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/SESSION_SUMMARY.md +0 -0
  60. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/docs/superpowers/specs/2026-04-03-bugfixes-design.md +0 -0
  61. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jessica-jones-static-cable.md +0 -0
  62. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/jfox/__main__.py +0 -0
  63. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/pytest.ini +0 -0
  64. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/run_full_test.ps1 +0 -0
  65. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skill/evals/evals.json +0 -0
  66. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skill/knowledge-base-notes/SKILL.md +0 -0
  67. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skill/knowledge-base-workspace/SKILL.md +0 -0
  68. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skills-recommend/README.md +0 -0
  69. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skills-recommend/claude-code/jfox-health/SKILL.md +0 -0
  70. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skills-recommend/claude-code/jfox-init/SKILL.md +0 -0
  71. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/skills-recommend/claude-code/jfox-search/SKILL.md +0 -0
  72. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/COVERAGE_PLAN.md +0 -0
  73. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/MIGRATION.md +0 -0
  74. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/TESTS.md +0 -0
  75. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/integration/__init__.py +0 -0
  76. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/performance/__init__.py +0 -0
  77. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/test_suggest_links.py +0 -0
  78. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/unit/__init__.py +0 -0
  79. {jfox_cli-0.1.3 → jfox_cli-0.1.5}/tests/utils/__init__.py +0 -0
@@ -14,6 +14,7 @@ on:
14
14
  - 'jfox/**'
15
15
  - 'tests/**'
16
16
  - 'pyproject.toml'
17
+ - '.github/workflows/integration-test.yml'
17
18
  # 允许手动触发
18
19
  workflow_dispatch:
19
20
  inputs:
@@ -33,6 +34,32 @@ env:
33
34
  PYTHONUTF8: 1
34
35
 
35
36
  jobs:
37
+ # ============ Lint 检查 ============
38
+ lint:
39
+ runs-on: ubuntu-latest
40
+ steps:
41
+ - name: Checkout code
42
+ uses: actions/checkout@v4
43
+
44
+ - name: Set up Python
45
+ uses: actions/setup-python@v5
46
+ with:
47
+ python-version: '3.11'
48
+
49
+ - uses: astral-sh/setup-uv@v4
50
+ with:
51
+ version: "latest"
52
+ enable-cache: true
53
+
54
+ - name: Install dependencies
55
+ run: uv sync --extra dev
56
+
57
+ - name: Run ruff check
58
+ run: uv run ruff check jfox/ tests/
59
+
60
+ - name: Run black check
61
+ run: uv run black --check jfox/ tests/
62
+
36
63
  # ============ 快速测试(PR 和 push 触发)============
37
64
  test-fast:
38
65
  runs-on: ${{ matrix.os }}
@@ -102,12 +129,20 @@ jobs:
102
129
  version: "latest"
103
130
  enable-cache: true
104
131
 
105
- - name: Cache model
132
+ - name: Cache model (Unix)
133
+ if: runner.os != 'Windows'
106
134
  uses: actions/cache@v4
107
135
  with:
108
136
  path: ~/.cache/torch/sentence_transformers
109
137
  key: ${{ runner.os }}-sentence-transformers-all-MiniLM-L6-v2
110
138
 
139
+ - name: Cache model (Windows)
140
+ if: runner.os == 'Windows'
141
+ uses: actions/cache@v4
142
+ with:
143
+ path: ~\AppData\Local\torch\sentence_transformers
144
+ key: ${{ runner.os }}-sentence-transformers-all-MiniLM-L6-v2
145
+
111
146
  - name: Install dependencies
112
147
  run: uv sync --extra dev
113
148
 
@@ -152,12 +187,20 @@ jobs:
152
187
  version: "latest"
153
188
  enable-cache: true
154
189
 
155
- - name: Cache model
190
+ - name: Cache model (Unix)
191
+ if: runner.os != 'Windows'
156
192
  uses: actions/cache@v4
157
193
  with:
158
194
  path: ~/.cache/torch/sentence_transformers
159
195
  key: ${{ runner.os }}-sentence-transformers-all-MiniLM-L6-v2
160
196
 
197
+ - name: Cache model (Windows)
198
+ if: runner.os == 'Windows'
199
+ uses: actions/cache@v4
200
+ with:
201
+ path: ~\AppData\Local\torch\sentence_transformers
202
+ key: ${{ runner.os }}-sentence-transformers-all-MiniLM-L6-v2
203
+
161
204
  - name: Install dependencies
162
205
  run: uv sync --extra dev
163
206
 
@@ -178,7 +221,25 @@ jobs:
178
221
  path: |
179
222
  .pytest_cache/
180
223
 
181
- # ============ 覆盖率报告汇总 ============
224
+ # ============ 质量门禁(所有必须测试通过才算成功)============
225
+ quality-gate:
226
+ runs-on: ubuntu-latest
227
+ needs: [lint, test-fast]
228
+ if: always()
229
+ steps:
230
+ - name: Check all jobs passed
231
+ run: |
232
+ echo "lint: ${{ needs.lint.result }}"
233
+ echo "test-fast: ${{ needs.test-fast.result }}"
234
+ if [[ "${{ needs.lint.result }}" == "success" && "${{ needs.test-fast.result }}" == "success" ]]; then
235
+ echo "Quality gate passed!"
236
+ exit 0
237
+ else
238
+ echo "Quality gate FAILED!"
239
+ exit 1
240
+ fi
241
+
242
+ # ============ 覆盖率报告(仅 fast 测试通过后)============
182
243
  coverage:
183
244
  runs-on: ubuntu-latest
184
245
  needs: [test-fast]
@@ -203,9 +264,42 @@ jobs:
203
264
 
204
265
  - name: Run coverage
205
266
  run: |
206
- uv run pytest tests/ -m "not embedding and not slow" --cov=jfox --cov-report=xml --cov-report=html -v --timeout=300
267
+ uv run pytest tests/ -m "not embedding and not slow" --cov=jfox --cov-report=xml --cov-report=html --cov-report=term -v --timeout=300
207
268
  timeout-minutes: 25
208
269
 
270
+ - name: Post coverage comment on PR
271
+ if: github.event_name == 'pull_request'
272
+ env:
273
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
274
+ run: |
275
+ python -c "
276
+ import xml.etree.ElementTree as ET
277
+ import subprocess
278
+
279
+ tree = ET.parse('coverage.xml')
280
+ root = tree.getroot()
281
+ rate = float(root.attrib['line-rate'])
282
+ lines_covered = int(root.attrib['lines-covered'])
283
+ lines_valid = int(root.attrib['lines-valid'])
284
+
285
+ rows = []
286
+ for cls in root.iter('class'):
287
+ name = cls.attrib['filename']
288
+ r = float(cls.attrib['line-rate'])
289
+ rows.append((name, r))
290
+ rows.sort(key=lambda x: x[1])
291
+
292
+ comment = '## Test Coverage\n\n'
293
+ comment += '**Overall: {:.1f}%** ({}/{} lines)\n\n'.format(rate * 100, lines_covered, lines_valid)
294
+ comment += '| Module | Coverage | Status |\n|--------|----------|--------|\n'
295
+ for name, r in rows:
296
+ icon = ':green_circle:' if r >= 0.8 else ':yellow_circle:' if r >= 0.5 else ':red_circle:'
297
+ comment += '| {} | {:.1f}% | {} |\n'.format(name, r * 100, icon)
298
+
299
+ pr = '${{ github.event.pull_request.number }}'
300
+ subprocess.run(['gh', 'pr', 'comment', pr, '--body', comment])
301
+ "
302
+
209
303
  - name: Upload coverage report
210
304
  uses: actions/upload-artifact@v4
211
305
  with:
@@ -91,6 +91,7 @@ Notes are Markdown files with YAML frontmatter stored under `~/.zettelkasten/<kb
91
91
 
92
92
  ## Conventions
93
93
 
94
+ - **Version bump**: 发版时必须同时修改 `pyproject.toml` 和 `jfox/__init__.py` 两处版本号(曾有 #88 遗漏 `__init__.py` 的教训)
94
95
  - **Line length**: 100 chars (black + ruff configured in `pyproject.toml`)
95
96
  - **Comments/docs**: Chinese (中文)
96
97
  - **Adding a CLI command**: Add `@app.command()` in `cli.py`, implement `_xxx_impl()` helper, add `--kb` and `--format json` support
@@ -125,6 +126,10 @@ Four jobs in `.github/workflows/integration-test.yml`:
125
126
  - Set `PYTHONUTF8=1` and `chcp 65001` for encoding
126
127
  - HuggingFace mirror for China: `export HF_ENDPOINT=https://hf-mirror.com`
127
128
 
129
+ ## Branch Rules
130
+
131
+ - **main 是保护分支**,不能直接 commit 或 push。所有改动必须通过新分支 + PR 合入。
132
+
128
133
  ## Gotchas
129
134
 
130
135
  - `pytest.ini` `addopts` includes `-v`, so `pytest tests/` already runs verbose — adding `-v` manually is redundant
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jfox-cli
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: JFox - Zettelkasten 知识管理 CLI 工具
5
5
  Project-URL: Homepage, https://github.com/zhuxixi/jfox
6
6
  Project-URL: Repository, https://github.com/zhuxixi/jfox
@@ -1,5 +1,5 @@
1
1
  """JFox - Zettelkasten 知识管理工具"""
2
2
 
3
- __version__ = "0.1.3"
3
+ __version__ = "0.1.5"
4
4
  __author__ = "User"
5
5
  __email__ = "user@example.com"