jfox-cli 0.6.0__tar.gz → 0.7.1__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.
- jfox_cli-0.7.1/.claude/skills/ci/SKILL.md +113 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/CHANGELOG.md +29 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/PKG-INFO +1 -1
- jfox_cli-0.7.1/docs/superpowers/plans/2026-04-29-daemon-stop-fix.md +306 -0
- jfox_cli-0.7.1/docs/superpowers/plans/2026-05-03-jfox-check.md +300 -0
- jfox_cli-0.7.1/docs/superpowers/plans/2026-05-03-list-notes-skip-summary.md +186 -0
- jfox_cli-0.7.1/docs/superpowers/plans/2026-05-03-log-level-fix.md +37 -0
- jfox_cli-0.7.1/docs/superpowers/plans/2026-05-04-list-notes-index.md +938 -0
- jfox_cli-0.7.1/docs/superpowers/specs/2026-04-29-daemon-stop-fix-design.md +85 -0
- jfox_cli-0.7.1/docs/superpowers/specs/2026-04-30-jfox-kb-env-var-design.md +70 -0
- jfox_cli-0.7.1/docs/superpowers/specs/2026-05-03-jfox-check-design.md +81 -0
- jfox_cli-0.7.1/docs/superpowers/specs/2026-05-03-list-notes-skip-summary-design.md +32 -0
- jfox_cli-0.7.1/docs/superpowers/specs/2026-05-03-log-level-fix-design.md +25 -0
- jfox_cli-0.7.1/docs/superpowers/specs/2026-05-04-list-notes-index-design.md +121 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/__init__.py +1 -1
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/cli.py +210 -52
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/config.py +2 -1
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/model_downloader.py +75 -18
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/note.py +50 -26
- jfox_cli-0.7.1/jfox/note_index.py +221 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/pyproject.toml +1 -1
- jfox_cli-0.7.1/tests/unit/test_check.py +120 -0
- jfox_cli-0.7.1/tests/unit/test_list_notes_skip.py +86 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_model_downloader.py +24 -0
- jfox_cli-0.7.1/tests/unit/test_note_index.py +281 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/uv.lock +1 -1
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.claude/settings.local.json +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.claude/skills/release/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.claude/skills/release/release_helper.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.githooks/pre-push +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.github/workflows/integration-test.yml +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.github/workflows/publish.yml +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.gitignore +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/.python-version +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/AGENTS.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/CLAUDE.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/DEVELOPMENT_PLAN.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/README.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/SESSION.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/SESSION_SUMMARY.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/installation.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-11-bulk-import-bm25-fix.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-11-edit-command.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-11-unify-format-option.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-ci-coverage-optimization.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-edit-content-file.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-fix-index-rebuild-clear.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-fix-index-verify-id-mismatch.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-fix-jfox-health-skill-kb-param.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-index-kb-param.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-lazy-import-perf.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-12-skill-redesign.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-13-add-content-file.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-13-bulk-import-vectorstore-init.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-13-ingest-log-command.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-13-ingest-skill-sync.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-13-suppress-third-party-logging.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-13-sync-skills-with-cli.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-14-sync-docs-daemon-show.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-15-gpu-embedding.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-15-make-daemon-deps-required.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-15-session-summary-confirmation.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-16-fix-windows-daemon-console-window.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-18-daemon-timeout-and-index-rebuild.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-22-release-skill.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-26-fix-daemon-deprecation-warnings.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-27-intranet-model-download.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/plans/2026-04-28-tag-filtering.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-03-bugfixes-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-12-skill-redesign-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-13-pr-auto-code-review-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-14-show-command-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-15-gpu-embedding-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-15-session-summary-confirmation-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-21-release-skill-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-26-fix-daemon-deprecation-warnings-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-27-intranet-model-download-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/superpowers/specs/2026-04-28-tag-filtering-design.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/docs/troubleshooting.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jessica-jones-static-cable.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/__main__.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/bm25_index.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/daemon/__init__.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/daemon/__main__.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/daemon/client.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/daemon/process.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/daemon/server.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/embedding_backend.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/formatters.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/git_extractor.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/global_config.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/graph.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/indexer.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/kb_manager.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/models.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/performance.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/search_engine.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/template.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/template_cli.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/jfox/vector_store.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/pytest.ini +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/run_full_test.ps1 +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/scripts/download-model-intranet.sh +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/README.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/claude-code/jfox-common/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/claude-code/jfox-ingest/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/claude-code/jfox-organize/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/claude-code/jfox-search/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/claude-code/jfox-session-summary/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/kimi-cli/jfox-common/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/kimi-cli/jfox-ingest/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/kimi-cli/jfox-organize/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/kimi-cli/jfox-search/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/skills-recommend/kimi-cli/jfox-session-summary/SKILL.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/COVERAGE_PLAN.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/MIGRATION.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/TESTS.md +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/conftest.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/integration/__init__.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/integration/test_backlinks.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/integration/test_model_download.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/integration/test_tag_filter_cli.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/performance/__init__.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/performance/test_performance.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_advanced_features.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_cli_format.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_config_set_unit.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_config_unit.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_core_workflow.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_embedding_device.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_hybrid_search.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_integration.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_kb_current.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/test_suggest_links.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/__init__.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_bm25_batch.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_daemon_process.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_edit.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_format_unify.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_formatters.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_git_extractor.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_global_config.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_index_kb_param.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_indexer_clear_before_rebuild.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_indexer_verify.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_kb_manager.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_lazy_import.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_logging_config.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_release_helper.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_show.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_tag_filter.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_template.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_template_cli.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_use_kb_env_var.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/unit/test_vector_store_clear.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/utils/__init__.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/utils/assertions.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/utils/jfox_cli.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/tests/utils/note_generator.py +0 -0
- {jfox_cli-0.6.0 → jfox_cli-0.7.1}/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,35 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to jfox-cli will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.7.1] - 2026-05-05
|
|
6
|
+
|
|
7
|
+
### Fixes
|
|
8
|
+
- dynamically detect model weight file format
|
|
9
|
+
|
|
10
|
+
[0.7.1]: https://github.com/zhuxixi/jfox/compare/v0.7.0...v0.7.1
|
|
11
|
+
|
|
12
|
+
## [0.7.0] - 2026-05-05
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
- **skills**: add CI monitoring with auto-polling to /ci command
|
|
16
|
+
- **skills**: add /ci command to trigger GitHub Actions workflows
|
|
17
|
+
- **cli**: add jfox check command for detecting corrupt files (#189)
|
|
18
|
+
- **note**: list_notes 扫描结束时汇总无效文件提示 (#188)
|
|
19
|
+
|
|
20
|
+
### Fixes
|
|
21
|
+
- **note**: downgrade parse failure log to warning in load_note (#187)
|
|
22
|
+
|
|
23
|
+
### Changes
|
|
24
|
+
- add design specs and implementation plans for recent features
|
|
25
|
+
- list_notes() 元数据索引,减少全量加载 (#190)
|
|
26
|
+
- add implementation plan for list_notes metadata index (#190)
|
|
27
|
+
- add spec for list_notes() metadata index (#190)
|
|
28
|
+
- add spec for jfox check command (#189)
|
|
29
|
+
- add spec for list_notes skip summary (#188)
|
|
30
|
+
- **spec**: add design for load_note log level fix (#186)
|
|
31
|
+
|
|
32
|
+
[0.7.0]: https://github.com/zhuxixi/jfox/compare/v0.6.0...v0.7.0
|
|
33
|
+
|
|
5
34
|
## [0.5.0] - 2026-04-29
|
|
6
35
|
|
|
7
36
|
### Features
|
|
@@ -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
|
+
```
|