7.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project
GYXX Flow is a Python 3.12 modular-monolith business automation platform. It orchestrates 23 scheduled workflows across four business domains (content marketing, product commerce, shop intelligence, supply chain) with LangGraph, runs them through a resident Python scheduler, and audits every run. Documentation, commit messages, and config descriptions are largely in Chinese; follow the existing language of each file.
Common Commands
Everything runs through uv from the repo root:
uv sync --python 3.12 --group dev # create/update dev environment
uv run pytest # full test suite
uv run pytest tests/test_cli.py # single test file
uv run pytest tests/path/test_x.py::test_name -k pattern # focused tests
uv run ruff check src tests # lint (E4, E7, E9, F, I)
uv build # distribution artifacts
CLI (entry point gyxx_flow.cli:main). Manual execution is dry-run by default; real external side effects require an explicit --execute flag:
uv run gyxx list # scheduled workflows only
uv run gyxx run product.daily --date 2026-08-01 # dry-run one workflow
uv run gyxx run product.daily --date 2026-08-01 --execute
uv run gyxx backfill content.metrics.daily --from <d> --to <d>
uv run gyxx scripts run <script_id> --date <d> # manual backfill/retry/maintenance
uv run gyxx schedule run --dry-run --once # scheduler; omit --dry-run to execute
uv run gyxx doctor --json # environment/config preflight
uv run gyxx acceptance status --json
uv run gyxx sources status --source-root <module>=<dir> # upstream source drift check
Manual/backfill commands must be declared in config/commands.json; never reintroduce recursive executable-script discovery. gyxx schedule run is the only production scheduling path — do not add Windows Task Scheduler tasks or extra cron entries.
Architecture
Execution pipeline: CLI / scheduler_service.py → WorkflowCatalog (parses config/workflows.json) → WorkflowRegistry + per-module factories → build_catalog_workflow (workflow/factory.py) compiles each workflow into a LangGraph StateGraph → WorkflowEngine (workflow/engine.py) executes steps with retries, resource locks, timeouts, and effect-ledger guards. Every run gets a stable run_id and records node status, logs, artifacts, locks, and external side effects in the RunJournal and EffectLedger (ops/effects.py). Preserve the public contracts of the workflow model, journal, locks, shadow comparison, and effect ledger when changing graph execution.
Layer boundaries (enforced by tests):
src/gyxx_flow/core/— settings,RunContext,DataLayout,LockManager,RunJournal, artifacts, exit codes.src/gyxx_flow/workflow/—StepDefinition/WorkflowDefinition(validated models),ExecutableStepprotocol, graph compilation, engine.src/gyxx_flow/adapters/— the only sanctioned bridge to infrastructure: PostgreSQL/Feishu/Hermes outboxes (external.py), browser profile/CDP management (browser.py), runtime service binding for child scripts (integration.py), module command resolution (native.py), acceptance/cookie policy (acceptance_policy.py).src/gyxx_flow/modules/<module>/— the four business modules (content_marketing,product_commerce,shop_intelligence,supply_chain). Business modules may depend only on shared contracts above — never on another module's internals. New production code goes directly in the module directory; theruntime/subpackages are legacy import-compatibility namespaces only.src/gyxx_flow/ops/,source_sync/,security/,baseline/— effect ledger/run index, manifest-driven source-drift tooling, secret scanning, engineering baselines.
Configuration quartet in config/ (all are validated at startup):
workflows.json— scheduled workflows only: stable id, module, explicit steps (entry script, args,depends_on,run_after_failure), failure policy. Each entry must have exactly one schedule.schedules.json— time rules only (allAsia/Shanghai; a day plan may have multiple times). Scheduler (scheduler_service.py) owns business-date offsets, slot dedup, non-overlap, missed-trigger compensation, graceful stop.commands.json— manual-execution whitelist (backfill, retry, mapping refresh, protected writes).--daterenders a command's declared{business_date}defaults; these are never new scheduled workflows.runtime-bindings.json— each browser script gets a unique CDP port plus isolated Profile/Cookie/storage-state; never share writable profiles. Scripts that use the same account may declare anaccountid (see the top-levelaccountssection): the account vault understate/accounts/<id>/is the single login authority, and its cookies are merged read-only into every member script's cookie files before each run (gyxx accounts login/sync). Member profiles stay isolated so parallel runs never contend.
External systems (all accessed through adapters):
- PostgreSQL: runtime-injected cloud DSN via
GYXX_POSTGRES_DSN(mapped toPG_*/DB_*/AUTOFLOW_PG_*). No address/credentials defaults in source; loopback DB addresses are rejected in cloud mode. - Hermes: loopback-only roles — analyzer
http://127.0.0.1:8642/v1, collectorhttp://127.0.0.1:8643/v1; key viaGYXX_HERMES_API_KEY. Non-loopback Hermes addresses are rejected. Pure-collection workflows run without AI; analysis/notification workflows need the local roles. - Feishu: keeps the existing lark-cli profile/app identity.
- Steps declare
production_sink,official_notification, andreplay_policy(guarded/idempotent); the engine and effect ledger enforce these gates.
Data layout: all runtime paths derive from GYXX_DATA_ROOT (dev default var/, which is gitignored generated state — never commit it or write source into it; production must use an external root). Layers: data/{raw,normalized,curated,exports,evidence}/<module>, state/ (scheduler, graph, locks, ledger, per-script browser state), logs/, tmp/. Raw data is append-only.
Repo-Specific Rules
- Ruff lint baseline:
src/gyxx_flow/modules/*/**is excluded viaextend-excludeinpyproject.toml(migrated scripts keep their old baseline). CI additionally lints a focused list of critical module scripts (see.gitlab-ci.yml); when adding or substantially changing module scripts that must be linted, add them to that focused CI list. - Adding a scheduled workflow: implement an independently testable entry in
modules/<module>/, declare steps inworkflows.json, add exactly one schedule rule, register commands and browser bindings as needed, access infrastructure only through shared adapters, and add dry-run/boundary/business-date regression tests. Backfill/maintenance capabilities are registered as commands only — they become workflows only when they become independent recurring jobs. New modules must not require changes to other modules; new steps must not require changes to the scheduler or engine. - Source sync (
gyxx sources status/apply): manifest-driven three-way hash comparison against upstream module source dirs; only untransformed, conflict-free one-sided changes may be auto-copied, and only with--execute. Cookies, profiles, credentials, logs, and collected data never enter sync manifests. - Tests live in
tests/(pytest,test_*.py); never require live credentials or mutate production services. Changes to workflows, schedules, manifests, runtime paths, or CLI behavior need acceptance or boundary coverage. - Use Conventional Commit subjects (e.g.
feat: consolidate legacy workflows). Never commit secrets, cookies,.envfiles, orvar/contents. - See
docs/architecture.md,docs/deployment.md,docs/runbook.md, anddocs/acceptance-report.mdfor operational detail.