jfox-cli 0.6.0__tar.gz → 0.7.0__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 (160) hide show
  1. jfox_cli-0.7.0/.claude/skills/ci/SKILL.md +113 -0
  2. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/CHANGELOG.md +22 -0
  3. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/PKG-INFO +1 -1
  4. jfox_cli-0.7.0/docs/superpowers/plans/2026-04-29-daemon-stop-fix.md +306 -0
  5. jfox_cli-0.7.0/docs/superpowers/plans/2026-05-03-jfox-check.md +300 -0
  6. jfox_cli-0.7.0/docs/superpowers/plans/2026-05-03-list-notes-skip-summary.md +186 -0
  7. jfox_cli-0.7.0/docs/superpowers/plans/2026-05-03-log-level-fix.md +37 -0
  8. jfox_cli-0.7.0/docs/superpowers/plans/2026-05-04-list-notes-index.md +938 -0
  9. jfox_cli-0.7.0/docs/superpowers/specs/2026-04-29-daemon-stop-fix-design.md +85 -0
  10. jfox_cli-0.7.0/docs/superpowers/specs/2026-04-30-jfox-kb-env-var-design.md +70 -0
  11. jfox_cli-0.7.0/docs/superpowers/specs/2026-05-03-jfox-check-design.md +81 -0
  12. jfox_cli-0.7.0/docs/superpowers/specs/2026-05-03-list-notes-skip-summary-design.md +32 -0
  13. jfox_cli-0.7.0/docs/superpowers/specs/2026-05-03-log-level-fix-design.md +25 -0
  14. jfox_cli-0.7.0/docs/superpowers/specs/2026-05-04-list-notes-index-design.md +121 -0
  15. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/__init__.py +1 -1
  16. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/cli.py +210 -52
  17. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/config.py +2 -1
  18. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/note.py +50 -26
  19. jfox_cli-0.7.0/jfox/note_index.py +221 -0
  20. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/pyproject.toml +1 -1
  21. jfox_cli-0.7.0/tests/unit/test_check.py +120 -0
  22. jfox_cli-0.7.0/tests/unit/test_list_notes_skip.py +86 -0
  23. jfox_cli-0.7.0/tests/unit/test_note_index.py +281 -0
  24. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/uv.lock +1 -1
  25. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.claude/settings.local.json +0 -0
  26. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.claude/skills/release/SKILL.md +0 -0
  27. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.claude/skills/release/release_helper.py +0 -0
  28. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.githooks/pre-push +0 -0
  29. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.github/workflows/integration-test.yml +0 -0
  30. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.github/workflows/publish.yml +0 -0
  31. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.gitignore +0 -0
  32. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/.python-version +0 -0
  33. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/AGENTS.md +0 -0
  34. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/CLAUDE.md +0 -0
  35. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/DEVELOPMENT_PLAN.md +0 -0
  36. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/README.md +0 -0
  37. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/SESSION.md +0 -0
  38. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/SESSION_SUMMARY.md +0 -0
  39. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/installation.md +0 -0
  40. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-11-bulk-import-bm25-fix.md +0 -0
  41. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-11-edit-command.md +0 -0
  42. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-11-unify-format-option.md +0 -0
  43. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-ci-coverage-optimization.md +0 -0
  44. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-edit-content-file.md +0 -0
  45. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-fix-index-rebuild-clear.md +0 -0
  46. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-fix-index-verify-id-mismatch.md +0 -0
  47. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-fix-jfox-health-skill-kb-param.md +0 -0
  48. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-index-kb-param.md +0 -0
  49. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-lazy-import-perf.md +0 -0
  50. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-12-skill-redesign.md +0 -0
  51. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-13-add-content-file.md +0 -0
  52. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-13-bulk-import-vectorstore-init.md +0 -0
  53. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-13-ingest-log-command.md +0 -0
  54. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-13-ingest-skill-sync.md +0 -0
  55. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-13-suppress-third-party-logging.md +0 -0
  56. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-13-sync-skills-with-cli.md +0 -0
  57. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-14-sync-docs-daemon-show.md +0 -0
  58. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-15-gpu-embedding.md +0 -0
  59. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-15-make-daemon-deps-required.md +0 -0
  60. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-15-session-summary-confirmation.md +0 -0
  61. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-16-fix-windows-daemon-console-window.md +0 -0
  62. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-18-daemon-timeout-and-index-rebuild.md +0 -0
  63. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-22-release-skill.md +0 -0
  64. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-26-fix-daemon-deprecation-warnings.md +0 -0
  65. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-27-intranet-model-download.md +0 -0
  66. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/plans/2026-04-28-tag-filtering.md +0 -0
  67. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-03-bugfixes-design.md +0 -0
  68. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-12-skill-redesign-design.md +0 -0
  69. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-13-pr-auto-code-review-design.md +0 -0
  70. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-14-show-command-design.md +0 -0
  71. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-15-gpu-embedding-design.md +0 -0
  72. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-15-session-summary-confirmation-design.md +0 -0
  73. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-21-release-skill-design.md +0 -0
  74. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-26-fix-daemon-deprecation-warnings-design.md +0 -0
  75. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-27-intranet-model-download-design.md +0 -0
  76. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/superpowers/specs/2026-04-28-tag-filtering-design.md +0 -0
  77. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/docs/troubleshooting.md +0 -0
  78. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jessica-jones-static-cable.md +0 -0
  79. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/__main__.py +0 -0
  80. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/bm25_index.py +0 -0
  81. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/daemon/__init__.py +0 -0
  82. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/daemon/__main__.py +0 -0
  83. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/daemon/client.py +0 -0
  84. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/daemon/process.py +0 -0
  85. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/daemon/server.py +0 -0
  86. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/embedding_backend.py +0 -0
  87. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/formatters.py +0 -0
  88. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/git_extractor.py +0 -0
  89. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/global_config.py +0 -0
  90. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/graph.py +0 -0
  91. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/indexer.py +0 -0
  92. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/kb_manager.py +0 -0
  93. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/model_downloader.py +0 -0
  94. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/models.py +0 -0
  95. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/performance.py +0 -0
  96. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/search_engine.py +0 -0
  97. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/template.py +0 -0
  98. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/template_cli.py +0 -0
  99. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/jfox/vector_store.py +0 -0
  100. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/pytest.ini +0 -0
  101. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/run_full_test.ps1 +0 -0
  102. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/scripts/download-model-intranet.sh +0 -0
  103. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/README.md +0 -0
  104. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/claude-code/jfox-common/SKILL.md +0 -0
  105. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/claude-code/jfox-ingest/SKILL.md +0 -0
  106. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/claude-code/jfox-organize/SKILL.md +0 -0
  107. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/claude-code/jfox-search/SKILL.md +0 -0
  108. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/claude-code/jfox-session-summary/SKILL.md +0 -0
  109. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/kimi-cli/jfox-common/SKILL.md +0 -0
  110. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/kimi-cli/jfox-ingest/SKILL.md +0 -0
  111. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/kimi-cli/jfox-organize/SKILL.md +0 -0
  112. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/kimi-cli/jfox-search/SKILL.md +0 -0
  113. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/skills-recommend/kimi-cli/jfox-session-summary/SKILL.md +0 -0
  114. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/COVERAGE_PLAN.md +0 -0
  115. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/MIGRATION.md +0 -0
  116. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/TESTS.md +0 -0
  117. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/conftest.py +0 -0
  118. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/integration/__init__.py +0 -0
  119. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/integration/test_backlinks.py +0 -0
  120. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/integration/test_model_download.py +0 -0
  121. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/integration/test_tag_filter_cli.py +0 -0
  122. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/performance/__init__.py +0 -0
  123. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/performance/test_performance.py +0 -0
  124. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_advanced_features.py +0 -0
  125. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_cli_format.py +0 -0
  126. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_config_set_unit.py +0 -0
  127. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_config_unit.py +0 -0
  128. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_core_workflow.py +0 -0
  129. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_embedding_device.py +0 -0
  130. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_hybrid_search.py +0 -0
  131. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_integration.py +0 -0
  132. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_kb_current.py +0 -0
  133. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/test_suggest_links.py +0 -0
  134. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/__init__.py +0 -0
  135. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_bm25_batch.py +0 -0
  136. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_daemon_process.py +0 -0
  137. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_edit.py +0 -0
  138. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_format_unify.py +0 -0
  139. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_formatters.py +0 -0
  140. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_git_extractor.py +0 -0
  141. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_global_config.py +0 -0
  142. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_index_kb_param.py +0 -0
  143. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_indexer_clear_before_rebuild.py +0 -0
  144. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_indexer_verify.py +0 -0
  145. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_kb_manager.py +0 -0
  146. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_lazy_import.py +0 -0
  147. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_logging_config.py +0 -0
  148. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_model_downloader.py +0 -0
  149. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_release_helper.py +0 -0
  150. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_show.py +0 -0
  151. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_tag_filter.py +0 -0
  152. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_template.py +0 -0
  153. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_template_cli.py +0 -0
  154. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_use_kb_env_var.py +0 -0
  155. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/unit/test_vector_store_clear.py +0 -0
  156. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/utils/__init__.py +0 -0
  157. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/utils/assertions.py +0 -0
  158. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/utils/jfox_cli.py +0 -0
  159. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/utils/note_generator.py +0 -0
  160. {jfox_cli-0.6.0 → jfox_cli-0.7.0}/tests/utils/temp_kb.py +0 -0
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: ci
3
+ description: Trigger GitHub Actions CI workflows. Supports fast, full, and core test types. Triggers on "跑测试", "trigger ci", "full test", "跑一下ci".
4
+ ---
5
+
6
+ # CI Skill
7
+
8
+ 通过 `gh` CLI 触发 GitHub Actions workflow,支持快速测试、全量测试和核心测试。
9
+
10
+ ## 用法
11
+
12
+ ```
13
+ /ci # 默认触发 fast 测试
14
+ /ci fast # 快速测试(跳过 embedding)
15
+ /ci full # 全量测试(所有 OS + Python 版本)
16
+ /ci core # 核心测试(含 embedding,main 分支专用)
17
+ ```
18
+
19
+ ## 执行步骤
20
+
21
+ ### Step 1: 解析参数
22
+
23
+ 从用户输入中提取测试类型,默认为 `fast`。合法值:`fast`、`full`、`core`。
24
+
25
+ ### Step 2: 触发 workflow
26
+
27
+ ```bash
28
+ gh workflow run integration-test.yml \
29
+ -f test_type=<type>
30
+ ```
31
+
32
+ ### Step 3: 获取 run ID 并展示链接
33
+
34
+ ```bash
35
+ # 等待几秒让 GitHub 创建 run
36
+ sleep 5
37
+
38
+ # 获取最新的 run
39
+ gh run list --workflow=integration-test.yml --limit 1 --json databaseId,status,htmlUrl
40
+ ```
41
+
42
+ 向用户展示:
43
+
44
+ ```
45
+ 已触发 <type> 测试: <run_url>
46
+ 可用 gh run watch <run_id> 监控进度。
47
+ ```
48
+
49
+ ### Step 4: 监听结果
50
+
51
+ 使用 CronCreate 创建定时轮询任务,自动检查 CI 状态并汇报结果。
52
+
53
+ 轮询间隔根据测试类型确定:
54
+
55
+ | 测试类型 | 预计耗时 | 轮询间隔 | 最大轮次 |
56
+ |---------|---------|---------|---------|
57
+ | full | ~60 min | 10 min | 8 次 |
58
+ | fast | ~30 min | 10 min | 5 次 |
59
+ | core | ~30 min | 10 min | 5 次 |
60
+
61
+ 创建 CronCreate 定时任务(非 durable):
62
+
63
+ ```
64
+ cron: "*/10 * * * *"
65
+ recurring: true
66
+ prompt: |
67
+ CI Monitor tick for run <run_id> (<type> test):
68
+
69
+ ## Step A: Check run status
70
+
71
+ Run: `gh run view <run_id> --json status,conclusion,jobs --jq '{status,conclusion}'`
72
+
73
+ - status: "completed" → check conclusion
74
+ - status: "in_progress" / "queued" / "waiting" → still running, continue
75
+
76
+ ## Step B: Report per-job status
77
+
78
+ Run: `gh run view <run_id> --json jobs --jq '.jobs[] | {name, status, conclusion}'`
79
+
80
+ Report each job's status:
81
+ - conclusion: "success" → ✅
82
+ - conclusion: "failure" → ❌
83
+ - status: "in_progress" / "queued" → ⏳
84
+
85
+ ## Step C: Decision
86
+
87
+ **If all jobs completed:**
88
+ - All success → Report "CI 全绿 ✅",取消 cron,告知用户
89
+ - Any failure → Report "CI 失败 ❌" 列出失败 job,取消 cron,建议查看日志:
90
+ `gh run view <run_id> --log-failed`
91
+
92
+ **If still running:**
93
+ - Increment tick counter
94
+ - If exceeded max rounds for this test type → 报告超时,取消 cron,建议手动检查
95
+ - Otherwise report current status and continue
96
+
97
+ ## Step D: Cancel on completion
98
+
99
+ When all jobs are done (success or failure), use CronDelete to cancel this monitoring job.
100
+ ```
101
+
102
+ 向用户展示:
103
+
104
+ ```
105
+ 已触发 <type> 测试: <run_url>
106
+ 预计耗时 ~<duration> 分钟,每 10 分钟检查一次进度。
107
+ ```
108
+
109
+ ## 错误处理
110
+
111
+ - workflow 不存在 → 提示检查 `.github/workflows/integration-test.yml`
112
+ - `gh` 未认证 → 提示运行 `gh auth login`
113
+ - 触发失败 → 展示错误信息
@@ -2,6 +2,28 @@
2
2
 
3
3
  All notable changes to jfox-cli will be documented in this file.
4
4
 
5
+ ## [0.7.0] - 2026-05-05
6
+
7
+ ### Features
8
+ - **skills**: add CI monitoring with auto-polling to /ci command
9
+ - **skills**: add /ci command to trigger GitHub Actions workflows
10
+ - **cli**: add jfox check command for detecting corrupt files (#189)
11
+ - **note**: list_notes 扫描结束时汇总无效文件提示 (#188)
12
+
13
+ ### Fixes
14
+ - **note**: downgrade parse failure log to warning in load_note (#187)
15
+
16
+ ### Changes
17
+ - add design specs and implementation plans for recent features
18
+ - list_notes() 元数据索引,减少全量加载 (#190)
19
+ - add implementation plan for list_notes metadata index (#190)
20
+ - add spec for list_notes() metadata index (#190)
21
+ - add spec for jfox check command (#189)
22
+ - add spec for list_notes skip summary (#188)
23
+ - **spec**: add design for load_note log level fix (#186)
24
+
25
+ [0.7.0]: https://github.com/zhuxixi/jfox/compare/v0.6.0...v0.7.0
26
+
5
27
  ## [0.5.0] - 2026-04-29
6
28
 
7
29
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jfox-cli
3
- Version: 0.6.0
3
+ Version: 0.7.0
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
@@ -0,0 +1,306 @@
1
+ # Fix daemon stop 无法停止 daemon — Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Fix `jfox daemon stop` so it reliably stops the daemon using HTTP `/shutdown` as primary mechanism, with taskkill/kill as fallback.
6
+
7
+ **Architecture:** Add a `POST /shutdown` endpoint to the daemon server that sets `uvicorn.Server.should_exit`. Rewrite `stop_daemon()` to call `/shutdown` first, then fall back to OS-level kill. Fix CLI to check the return value.
8
+
9
+ **Tech Stack:** Python, FastAPI, uvicorn, urllib
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-04-29-daemon-stop-fix-design.md`
12
+
13
+ ---
14
+
15
+ ## File Structure
16
+
17
+ | File | Action | Responsibility |
18
+ |------|--------|----------------|
19
+ | `jfox/daemon/server.py` | Modify | Add `/shutdown` endpoint, refactor `main()` to use `uvicorn.Server` directly |
20
+ | `jfox/daemon/process.py` | Modify | Rewrite `stop_daemon()` with HTTP-first flow, add `_http_shutdown()` helper |
21
+ | `jfox/cli.py` | Modify | Check `stop_daemon()` return value in daemon stop command |
22
+
23
+ ---
24
+
25
+ ### Task 1: Add /shutdown endpoint to server.py
26
+
27
+ **Files:**
28
+ - Modify: `jfox/daemon/server.py`
29
+
30
+ - [ ] **Step 1: Add global `_server` variable and `/shutdown` endpoint**
31
+
32
+ Add `_server = None` after the `_backend = None` line (line 20). Add the `/shutdown` endpoint after the `/health` endpoint (after line 98).
33
+
34
+ In `jfox/daemon/server.py`, the top of the file should have:
35
+
36
+ ```python
37
+ # 全局 embedding 后端(模型加载后常驻内存)
38
+ _backend = None
39
+
40
+ # uvicorn Server 实例(用于 graceful shutdown)
41
+ _server = None
42
+ ```
43
+
44
+ Add the `/shutdown` endpoint after the `/health` endpoint (after line 98):
45
+
46
+ ```python
47
+ @app.post("/shutdown")
48
+ def shutdown():
49
+ """请求 daemon 自行停止"""
50
+ global _server
51
+ if _server:
52
+ _server.should_exit = True
53
+ return {"status": "shutting_down"}
54
+ ```
55
+
56
+ - [ ] **Step 2: Refactor `main()` to use `uvicorn.Server` directly**
57
+
58
+ Replace the existing `main()` function (lines 126-140) with:
59
+
60
+ ```python
61
+ def main():
62
+ from . import DEFAULT_HOST, DEFAULT_PORT
63
+
64
+ parser = argparse.ArgumentParser(description="JFox Embedding Daemon")
65
+ parser.add_argument("--host", default=DEFAULT_HOST, help="监听地址")
66
+ parser.add_argument("--port", type=int, default=DEFAULT_PORT, help="监听端口")
67
+ args = parser.parse_args()
68
+
69
+ import uvicorn
70
+
71
+ global _server
72
+ config = uvicorn.Config(app, host=args.host, port=args.port, log_level="warning")
73
+ _server = uvicorn.Server(config)
74
+ _server.run()
75
+ ```
76
+
77
+ This replaces `uvicorn.run()` with manual `uvicorn.Server` + `_server.run()`, so the `/shutdown` endpoint can set `_server.should_exit = True`.
78
+
79
+ - [ ] **Step 3: Verify daemon starts correctly**
80
+
81
+ Run: `uv run python -c "from jfox.daemon.server import app; print('server module OK')"`
82
+
83
+ Expected: `server module OK` — confirms no import or syntax errors.
84
+
85
+ - [ ] **Step 4: Commit**
86
+
87
+ ```bash
88
+ git add jfox/daemon/server.py
89
+ git commit -m "feat(daemon): add /shutdown endpoint for graceful stop"
90
+ ```
91
+
92
+ ---
93
+
94
+ ### Task 2: Add _http_shutdown() helper and rewrite stop_daemon()
95
+
96
+ **Files:**
97
+ - Modify: `jfox/daemon/process.py`
98
+
99
+ - [ ] **Step 1: Add `_http_shutdown()` helper**
100
+
101
+ Add this function after `_http_health_check()` (after line 88) in `jfox/daemon/process.py`:
102
+
103
+ ```python
104
+ def _http_shutdown(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> bool:
105
+ """请求 daemon 通过 /shutdown endpoint 自行停止"""
106
+ try:
107
+ import urllib.request
108
+
109
+ req = urllib.request.Request(
110
+ f"http://{host}:{port}/shutdown", method="POST", data=b""
111
+ )
112
+ resp = urllib.request.urlopen(req, timeout=3)
113
+ result = json.loads(resp.read().decode("utf-8"))
114
+ return result.get("status") == "shutting_down"
115
+ except (OSError, ValueError):
116
+ return False
117
+ ```
118
+
119
+ - [ ] **Step 2: Rewrite `stop_daemon()` with HTTP-first flow**
120
+
121
+ Replace the entire `stop_daemon()` function (lines 261-308) with:
122
+
123
+ ```python
124
+ def stop_daemon() -> bool:
125
+ """
126
+ 停止 daemon 进程
127
+
128
+ Returns:
129
+ True 表示停止成功
130
+ """
131
+ data = _read_pid_file()
132
+ host = DEFAULT_HOST
133
+ port = DEFAULT_PORT
134
+ pid = 0
135
+
136
+ if data is not None:
137
+ pid = data.get("pid", 0)
138
+ host = data.get("host", DEFAULT_HOST)
139
+ port = data.get("port", DEFAULT_PORT)
140
+
141
+ # 先检查是否真的在跑
142
+ health = _http_health_check(host, port)
143
+ if health is None:
144
+ _remove_pid_file()
145
+ return True
146
+
147
+ # 1. 优先通过 HTTP /shutdown 让 daemon 自行退出
148
+ logger.info("正在通过 /shutdown 请求 daemon 停止...")
149
+ _http_shutdown(host, port)
150
+
151
+ # 等待 daemon 自行退出(最多 3 秒)
152
+ for _ in range(6):
153
+ if _http_health_check(host, port) is None:
154
+ _remove_pid_file()
155
+ logger.info("Daemon 已通过 /shutdown 停止")
156
+ return True
157
+ time.sleep(0.5)
158
+
159
+ # 2. /shutdown 失败,从 /health 获取真实 PID 后尝试 taskkill/kill
160
+ if pid == 0:
161
+ health = _http_health_check(host, port)
162
+ if health:
163
+ pid = health.get("pid", 0)
164
+
165
+ if pid > 0:
166
+ try:
167
+ if sys.platform == "win32":
168
+ subprocess.run(
169
+ ["taskkill", "/PID", str(pid), "/T", "/F"],
170
+ capture_output=True,
171
+ timeout=10,
172
+ )
173
+ else:
174
+ os.kill(pid, 15) # SIGTERM
175
+ except (OSError, subprocess.SubprocessError) as e:
176
+ logger.warning(f"停止 daemon 失败: {e}")
177
+
178
+ # 等待进程退出(最多 5 秒)
179
+ for _ in range(10):
180
+ if _http_health_check(host, port) is None:
181
+ _remove_pid_file()
182
+ logger.info(f"Daemon 已停止 (PID: {pid})")
183
+ return True
184
+ time.sleep(0.5)
185
+
186
+ # 超时未退出 — 不删 PID 文件,保留追踪信息
187
+ logger.warning(f"Daemon 停止超时 (PID: {pid})")
188
+ return False
189
+ ```
190
+
191
+ Key differences from the old version:
192
+ - `/shutdown` HTTP call is tried first (lines after "优先通过 HTTP")
193
+ - Health check loop after `/shutdown` waits up to 3 seconds
194
+ - If PID is 0, fetches real PID from `/health` response (the "Bug 1" fix)
195
+ - On timeout, does NOT remove PID file (the "Bug 3" fix)
196
+
197
+ - [ ] **Step 3: Verify module imports correctly**
198
+
199
+ Run: `uv run python -c "from jfox.daemon.process import stop_daemon; print('process module OK')"`
200
+
201
+ Expected: `process module OK`
202
+
203
+ - [ ] **Step 4: Commit**
204
+
205
+ ```bash
206
+ git add jfox/daemon/process.py
207
+ git commit -m "fix(daemon): rewrite stop_daemon with HTTP-first shutdown"
208
+ ```
209
+
210
+ ---
211
+
212
+ ### Task 3: Fix CLI to check stop_daemon() return value
213
+
214
+ **Files:**
215
+ - Modify: `jfox/cli.py:2657-2663`
216
+
217
+ - [ ] **Step 1: Update daemon stop branch to check return value**
218
+
219
+ In `jfox/cli.py`, replace lines 2657-2663:
220
+
221
+ ```python
222
+ elif action == "stop":
223
+ if not is_daemon_running():
224
+ console.print("[dim]Daemon 未运行[/dim]")
225
+ return
226
+ console.print("[yellow]正在停止 daemon...[/yellow]")
227
+ stop_daemon()
228
+ console.print("[green]✓ Daemon 已停止[/green]")
229
+ ```
230
+
231
+ with:
232
+
233
+ ```python
234
+ elif action == "stop":
235
+ if not is_daemon_running():
236
+ console.print("[dim]Daemon 未运行[/dim]")
237
+ return
238
+ console.print("[yellow]正在停止 daemon...[/yellow]")
239
+ if stop_daemon():
240
+ console.print("[green]✓ Daemon 已停止[/green]")
241
+ else:
242
+ console.print("[red]✗ Daemon 停止失败,请手动终止进程[/red]")
243
+ raise typer.Exit(1)
244
+ ```
245
+
246
+ This fixes "Bug 2" — the CLI now reports failure when `stop_daemon()` returns `False`.
247
+
248
+ - [ ] **Step 2: Verify CLI module loads**
249
+
250
+ Run: `uv run python -c "from jfox.cli import app; print('cli module OK')"`
251
+
252
+ Expected: `cli module OK`
253
+
254
+ - [ ] **Step 3: Commit**
255
+
256
+ ```bash
257
+ git add jfox/cli.py
258
+ git commit -m "fix(cli): check stop_daemon return value in daemon stop command"
259
+ ```
260
+
261
+ ---
262
+
263
+ ### Task 4: Manual integration test
264
+
265
+ This task requires a running daemon and manual verification. Do not automate — provide commands for the user.
266
+
267
+ **Files:** None (testing only)
268
+
269
+ - [ ] **Step 1: Test normal stop path**
270
+
271
+ ```bash
272
+ uv run jfox daemon start
273
+ uv run jfox daemon stop
274
+ uv run jfox daemon status # should show "Daemon 未运行"
275
+ ```
276
+
277
+ Expected: stop succeeds, status shows not running.
278
+
279
+ - [ ] **Step 2: Test PID-file-missing fallback**
280
+
281
+ ```bash
282
+ uv run jfox daemon start
283
+ # Delete PID file to simulate the bug scenario
284
+ rm ~/.jfox_daemon.pid
285
+ uv run jfox daemon stop # should still succeed via /shutdown
286
+ uv run jfox daemon status # should show "Daemon 未运行"
287
+ ```
288
+
289
+ Expected: stop succeeds even without PID file, because `/shutdown` works without PID.
290
+
291
+ - [ ] **Step 3: Test stop when already stopped**
292
+
293
+ ```bash
294
+ uv run jfox daemon stop # daemon not running
295
+ ```
296
+
297
+ Expected: shows "Daemon 未运行" immediately.
298
+
299
+ - [ ] **Step 4: Final commit if any adjustments needed**
300
+
301
+ If any issues were found and fixed during manual testing, commit the fixes:
302
+
303
+ ```bash
304
+ git add -A
305
+ git commit -m "fix(daemon): adjustments from manual testing"
306
+ ```