Extract every Chinese string inside backend logger.{info,warning,error,
debug,exception} calls and inside user-facing jsonify({"error|message":
...}) responses across the listed in-scope modules into
locales/{en,zh}.json under nested namespaces (log.<module>.*,
api.{error,message}.<scope>.*). Locale dictionaries stay structurally
identical; the existing flat frontend-facing keys at log.* / api.* are
left untouched. The locale helper (backend/app/utils/locale.py) now
emits a single deduplicated mirofish.locale warning per (locale, key)
pair when a translation is missing instead of silently returning the
raw key, so unknown keys are visible without crashing requests or
background tasks. A repo-root scripts/check_i18n_logs.py verifier
performs an AST-aware source scan for residual Chinese inside the
in-scope logger/jsonify calls and a recursive parity diff between
en.json and zh.json — both modes pass.
Why: backend logs and API errors previously emitted Chinese-only
strings, leaving English-speaking operators with unreadable log
aggregator output and API consumers with locale-mismatched error
messages. The t() helper and per-thread set_locale propagation already
existed; this change makes every backend caller route through them.
Closes#6
translate every llm-facing string-literal in
backend/app/services/report_agent.py — the four tool-description
constants, the plan/section/chat system+user prompts, the react loop
templates, the inline messages re-injected during the section and chat
loops, the _execute_tool error returns, and the plan_outline default and
fallback outline content. preserve every {interpolation} token, the
literal final answer: trigger and <tool_call> xml tag, the four primary
tool names, and all three get_language_instruction() postfix call sites.
also switch the unused-tools join separator from "、" to ", " so it
renders naturally inside the now-english react templates.
removes the chinese language bias that the english postfix alone could
not overcome — under accept-language: en the report agent now produces
english-flavoured analytical reports and chat replies; under
accept-language: zh the postfix continues to steer the model into
chinese with no semantic delta. logger calls (#6) and docstrings or
comments (#7) are deliberately untouched.
Closes#5
Adds a Neo4j service to docker-compose so `docker compose up -d` works
on a clean checkout, and unhardcodes Graphiti's LLM/embedder so the
documented default provider (Qwen via Dashscope) actually works.
- docker-compose: neo4j:5-community service with cypher-shell
healthcheck, named volumes, and `depends_on: service_healthy` on the
app container; in-Docker NEO4J_URI override leaves the host-mode
default untouched.
- Config: new GRAPHITI_LLM_PROVIDER (openai|gemini, default openai) plus
optional EMBEDDING_API_KEY / EMBEDDING_BASE_URL that fall back to the
chat LLM credentials.
- graphiti_adapter: provider switch inside the singleton factory with
lazy per-provider imports; Gemini path is preserved exactly. The
no-op `_GeminiReranker` becomes a provider-agnostic
`_PassthroughReranker`, still injected explicitly so Graphiti does
not fall back to its OpenAI-only default reranker.
- Drop the ignored `reranker=` kwarg from `_GraphNamespace.search` and
the misleading callers in `zep_tools.py` and
`oasis_profile_generator.py`.
- Refresh `.env.example` to mirror the README env section.
Spec, requirements, and design under
`.kiro/specs/graphiti-neo4j-finalize/`.
Closes#1
Add .kiro/steering/ as persistent project memory for CC-SDD / Kiro
workflows. Three core files (product, tech, structure) capture
purpose, stack, and organization patterns; three custom files
(database, api-standards, error-handling) pin the load-bearing
project-specific conventions:
- group_id isolation and the Graphiti adapter / event-loop singleton
- {success, data|error} envelope and the Task polling contract
- reasoning-model output stripping and the retry_with_backoff helper
Files focus on patterns and decisions, not catalogs, per the
steering-principles "golden rule".
Adopt CC-SDD (Kiro) as the project's spec-driven planning tool, with
plans persisted in .kiro/specs/ and a checkpoint after every task
(strictest cadence — no code without an approved plan).
CC-SDD install (via npx cc-sdd@latest --claude --lang en):
- .kiro/settings/rules/: EARS format, gap-analysis, design and
requirements review gates, design discovery, tasks generation,
steering principles, parallel-task analysis.
- .kiro/settings/templates/: specs (init, requirements, design, tasks,
research) and steering (product/tech/structure plus optional
api-standards/auth/db/deployment/error-handling/security/testing).
- .claude/commands/kiro/: 11 Kiro slash commands — spec-init,
spec-requirements, spec-design, spec-tasks, spec-impl, spec-status,
steering, steering-custom, validate-gap, validate-design,
validate-impl.
Local additions:
- .claude/commands/plan.md: /plan [task] wrapper that picks up the task
from $ARGUMENTS or a single .ticket/<n>.md snapshot, walks the Kiro
flow (steering -> spec-init -> spec-requirements -> validate-gap ->
spec-design -> validate-design -> spec-tasks) and stops for human
approval after each artefact. Refuses "just code it" requests.
- .claude/hooks/session_start.sh: extend to print active tickets
(.ticket/*.md) and open specs (.kiro/specs/*/) with phase from
spec.json, alongside the existing branch/state line.
Documentation: .claude/onboarding/step4_workflow/01_tool_decision.md