refactor(mcp): extract order services into independent project

Remove Kingdee sync, business CLI/MCP tools, and internal order-query routing
now owned by the separate kingdee-orders-mcp project. Keep Wiki retrieval,
file assets and ingest available in code while its deployed service is off.
Retain legacy response fields with business access disabled, and document
migration ownership and rollback without exposing credentials or data.

Validation: 174 Wiki tests pass. Independent order service verified with
36 template parity checks, authenticated HTTP queries, and a real sync.
This commit is contained in:
Codex
2026-10-31 07:41:18 +00:00
parent 6c451c3eb6
commit 2396bd2d3e
25 changed files with 47 additions and 5793 deletions
+5 -53
View File
@@ -33,19 +33,16 @@ obsidian-wiki list # list the bundled skills
obsidian-wiki info # show install paths, version, and config
obsidian-wiki file-index rebuild # rebuild fast source-file lookup index
obsidian-wiki file-index search "FH52K 图纸" -n 10
obsidian-wiki business schema --json # business facts catalog used by wiki-query
obsidian-wiki setup --project . # also drop project-local skills + AGENTS.md into the current repo
obsidian-wiki setup --copy # copy skill files instead of symlinking
```
For operational questions such as "2026 年 6 月接了多少单", ask your agent with `wiki-query`. The `wiki-query` skill decides whether the question needs structured business facts, then uses the business template catalog or guarded read-only SQL before falling back to normal wiki retrieval. For hybrid questions about customers, products, salespeople, projects, delivery risk, anomalies, rankings, or quality impact, it runs a normal wiki context track and a business facts track, then fuses narrative context with structured metrics.
Operational sales-order queries and Kingdee synchronization now live in the independent `kingdee-orders-mcp` project. See [the migration note](docs/business-facts.md).
When working from a cloned repo, `scripts/obsidian-wiki-ops.py` is the single repo-local operations entrypoint. It wraps common `obsidian-wiki` commands, Kingdee business sync/templates, the business sync timer, daily update, and the managed MCP service:
When working from a cloned repo, `scripts/obsidian-wiki-ops.py` is the single repo-local operations entrypoint. It wraps common `obsidian-wiki` commands, daily update, and the managed MCP service:
```bash
scripts/obsidian-wiki-ops.py help
scripts/obsidian-wiki-ops.py kingdee sync --incremental
scripts/obsidian-wiki-ops.py timer install --vault /path/to/vault
scripts/obsidian-wiki-ops.py mcp start
```
@@ -325,54 +322,9 @@ obsidian-wiki file-index stage ./drawing.step --project bjd --doc-type drawing
Staging is for upload/intake only. The normal ingest flow should still classify the file, archive it under `_sources/archive/`, update source registry/catalog pages, and rebuild the file index.
### Optional: Business Fact Queries
### Independent order service
Operational counts and amounts belong in a structured fact database, not in markdown pages. The `business` CLI stores Kingdee sales orders in `<vault>/_meta/business-facts.sqlite`. Normal users should ask through `wiki-query`; the skill decides when to use structured business facts, prefers templates, and only falls back to guarded read-only SQL when no template fits. For mixed business-and-context questions, `wiki-query` runs a hybrid path: one track gathers wiki context and citations, another gathers read-only business metrics, and the final answer keeps the two sources clearly separated.
For multi-company data, set `OBSIDIAN_BUSINESS_INTERNAL_PARTIES` and/or `OBSIDIAN_BUSINESS_INTERNAL_PARTY_IDS` in `.env`. Built-in business templates then exclude intercompany transfer orders by default, but only when both the sales organization and ordering customer match internal parties. Direct external-customer orders to a factory are still counted. Use `--include-internal-orders` only when auditing internal transfer flow.
```bash
# Sync from an exported or API-fetched Kingdee JSON payload.
scripts/obsidian-wiki-ops.py kingdee sync --input ./kingdee-orders.json
# Or create the private local config for the real Kingdee API/token flow.
scripts/obsidian-wiki-ops.py kingdee config
vim .runtime/kingdee.env
scripts/obsidian-wiki-ops.py kingdee auth-test
# Then fetch reviewed June orders from Kingdee.
scripts/obsidian-wiki-ops.py kingdee sync \
--start-bizdate 2026-06-01 \
--end-bizdate 2026-06-30 \
--billstatus C
# Or fetch incrementally by Kingdee modify time.
scripts/obsidian-wiki-ops.py kingdee sync --incremental
# Inspect the schema/template catalog used by wiki-query.
scripts/obsidian-wiki-ops.py kingdee schema --json
# Run explicit templates for debugging or automation.
scripts/obsidian-wiki-ops.py kingdee template order_count --vault /path/to/vault --year 2026 --month 6 --json
scripts/obsidian-wiki-ops.py kingdee template sales_amount --vault /path/to/vault --year 2026 --month 6 --json
scripts/obsidian-wiki-ops.py kingdee template top_customers --vault /path/to/vault --year 2026 --month 6 --limit 10 --json
scripts/obsidian-wiki-ops.py kingdee template staff_order_list --vault /path/to/vault --start-date 2026-06-30 --end-date 2026-07-07 --staff 徐丽 --json
# Run guarded read-only SQL only when templates do not fit.
scripts/obsidian-wiki-ops.py kingdee sql "SELECT COUNT(*) AS order_count FROM orders"
```
Templates cover order counts, sales amounts, customer/product counts, quantity, averages, trends, rankings, breakdowns, order lists, customer/product/staff summaries, status breakdowns, and delivery-plan queries. Salesperson templates default to the main Kingdee salesperson and can include secondary/follow-up roles with `--staff-role-scope all`. If no template fits, `business sql` allows guarded read-only SQL against structured tables only; raw JSON and write statements are blocked. Detailed order rows stay in SQLite; the wiki remains for business context, customer/project knowledge, and cross-linked notes. Real Kingdee credentials live in `.runtime/kingdee.env`, and fetched tokens are cached in `.runtime/kingdee-token.json`; both files are local-only and ignored by git.
For daily unattended sync on Linux:
```bash
scripts/obsidian-wiki-ops.py timer install --vault /path/to/vault
scripts/obsidian-wiki-ops.py timer run-now --vault /path/to/vault
scripts/obsidian-wiki-ops.py timer status
```
The timer runs as a user-level systemd timer, defaults to `07:10` daily, and uses `--incremental` with a 48-hour lookback window.
Sales-order MCP tools, Kingdee synchronization, credentials, and the order database have moved to `kingdee-orders-mcp`. Wiki has no runtime dependency on that project. See [migration and rollback details](docs/business-facts.md).
### Optional: Source File MCP Server
@@ -522,7 +474,7 @@ This adds read-oriented OpenCode-backed query tools to the same `wiki-file-asset
The managed service config sets query to `OBSIDIAN_MCP_QUERY_OPENCODE_MODEL=openai/gpt-6.1-sol`, `OBSIDIAN_MCP_QUERY_OPENCODE_VARIANT=low`, and `OBSIDIAN_MCP_QUERY_JOB_TIMEOUT_SECONDS=300` by default, prioritizing response speed over maximum reasoning depth. Tune the server env file if a different balance is needed. GPT-6.1 Sol balances multi-step document/tool work and cost; query uses `low` for latency while ingest uses `high` for synthesis and metadata maintenance. GPT-5.5 retired from Codex with ChatGPT sign-in on October 14, 2026 ([model availability](https://learn.chatgpt.com/docs/models)). Existing installations must update their saved env file and restart the service; changing these defaults does not overwrite saved settings.
`public_only` defaults to `false`, so the answer may use the same full vault visibility that a local operator sees. Set `public_only=true` when the remote answer must exclude `visibility/internal` and `visibility/pii` pages. Job state and logs live under `.runtime/mcp-query/jobs/`, outside the vault; remote query status/result responses expose bounded, path-redacted text and omit local log paths. The final JSON text event must contain `MCP_QUERY_OK`; `MCP_QUERY_FAILED`, a missing marker, a nonzero exit, timeout, or cancellation cannot be reported as a successful answer. Query results keep the legacy `answer` field and also include `answer_markdown`, `citations`, `used_wiki`, `used_business_facts`, `data_freshness`, `warnings`, and `confidence` so agents can parse the response without scraping raw logs. A normal `wiki-query` log entry is allowed. The generated prompt instructs the agent to avoid ingest/update/rebuild workflows, writes, sync/config/timer operations, and arbitrary shell execution; it only permits the `obsidian-wiki business schema/template/sql` read-only commands needed by the wiki-query business facts route, but these prompt restrictions do not replace the trusted-client boundary described above. Hybrid business + wiki questions may run a wiki context track and a business facts track, using parallel subagents only when the host supports them and otherwise running sequentially. When `public_only=true`, business facts remain disabled.
`public_only` defaults to `false`, so the answer may use the same full vault visibility that a local operator sees. Set `public_only=true` when the remote answer must exclude `visibility/internal` and `visibility/pii` pages. Job state and logs live under `.runtime/mcp-query/jobs/`, outside the vault; remote query status/result responses expose bounded, path-redacted text and omit local log paths. The final JSON text event must contain `MCP_QUERY_OK`; `MCP_QUERY_FAILED`, a missing marker, a nonzero exit, timeout, or cancellation cannot be reported as a successful answer. Query results keep the legacy `answer` field and also include `answer_markdown`, `citations`, `used_wiki`, `used_business_facts`, `data_freshness`, `warnings`, and `confidence` so agents can parse the response without scraping raw logs. A normal `wiki-query` log entry is allowed. The generated prompt instructs the agent to avoid ingest/update/rebuild workflows, writes, sync/config/timer operations, and arbitrary shell execution. Operational order access belongs to the independent orders MCP; `used_business_facts` is retained for response compatibility and is always `false`.
Clean old MCP runtime staging data with the default 30-day retention window: