deer-flow/scripts/AGENTS.md
Xinmin Zeng 2a97ec3e58
docs: turn README into an index and move reference detail to docs/guide (#8113)
* docs: turn README into an index and move reference detail to docs/guide

The README had grown to 393 KB because every change appended its notes there. The text moves verbatim into 18 topic guides under docs/guide/; only headings are re-leveled and relative links re-pointed. The README keeps the introduction, a quick start and a guide index. Contributor test notes move to CONTRIBUTING.md.

* docs: send user docs to topic guides and budget the root README

The rule 'update README.md for user-facing changes' is what grew the README. Guidance now points to docs/guide/, and check_agent_guidance.py fails when the root README exceeds 16 KiB (AG003).

* chore: remove unreferenced screenshots and finished plan notes

pr-build/ holds two PR screenshots (3 MB) from #1986. plans/ holds the plan for the merged #4049. docs/SKILL_NAME_CONFLICT_FIX.md is a February change note. Nothing references them.

* docs: route always-loaded AGENTS.md files to scoped guides

* docs(agents): cut scoped guides to scope, verify, traps, decisions

Each AGENTS.md keeps four kinds of content: the scope of the directory, the
verification commands, traps a local test run does not show, and decisions the
code cannot state. Values, field lists, function inventories, test names, issue
numbers and history are deleted, because the code, the tests and git state them.

Search and fetch providers share one community guide. Four guides with no
remaining content are removed. The size check now allows 6 KiB per file (hard
limit 8 KiB) and 24 KiB per chain (hard limit 32 KiB).

* style: format frontend guide table and guidance test imports

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-11 13:26:17 +08:00

91 lines
4.7 KiB
Markdown

# Orchestration scripts (`scripts/`)
Scripts behind the root `Makefile`: local start and stop (`serve.sh`), Docker
development (`docker.sh`), production deployment (`deploy.sh`), setup and
diagnosis (`setup_wizard.py`, `doctor.py`, `support_bundle.py`), static analysis
and repository checks. Each script documents its own flags; run it with `--help`
or read its header.
## Verify
```bash
cd backend
python -m pytest tests -q -k "serve or deploy or compose or doctor or dotenv or script or wizard or support_bundle"
```
The shell suites run the real scripts against stub `docker` and `uv` binaries.
Cases marked for real Compose run only when a `docker` CLI is installed.
## Portability
- **Make recipes call `.sh` files through `RUN_SHELL_SCRIPT`**, and a script that
calls a sibling script prefixes it with `bash`. A source archive,
`core.fileMode=false` or a non-POSIX filesystem does not keep executable bits.
- **Host pnpm calls go through `scripts/pnpm.py`.** It chooses the launcher by
Python's `os.name`, not by the invoking shell, so native Windows, MSYS and POSIX
each get the right one.
- **Shell filters stay compatible with GNU and BSD sed**, because macOS ships
the BSD tools. `sandbox-mode.sh` uses Bash and awk only.
- **Lookups that run before the environment exists use the standard library
only.** Config detection, label checks and the dotenv helpers run before
`uv sync`.
- **Python entry points guard their stream encoding.** Windows consoles and
redirected CI logs are not UTF-8 by default, and embedded or captured streams
have no `reconfigure`. Read config and credential JSON with or without a BOM,
as the runtime loader does.
## Config and dotenv
- **Act on the file the Gateway would load.** `doctor.py` and `config-upgrade.sh`
ask the harness for the resolved config path. A fixed `config.yaml` path
diagnoses or upgrades the wrong file when an override is set.
- **Never source a dotenv file.** Parse it and quote path arguments. A dotenv
value overrides nothing that the shell exported, including an exported empty
value.
- **`deploy.sh` lets Compose parse `.env`.** Compose accepts forms that a
`KEY=VALUE` grep misses, so the script asks `docker compose config` what a key
resolves to. Do not export a value the script read from `.env`: that shadows
Compose's own parsing, and `make up` then replaces the operator's secret with a
generated one.
- **Secrets resolve shell, then `.env`, then the persisted file, then a new
value.** A failing probe stops the script; it does not guess.
- **One dotenv selection per deployment.** `DEER_FLOW_COMPOSE_ENV_FILE` is
resolved once, and Compose interpolation, service env files, secret probes and
extras detection all use that path.
- **Do not seed production `.env` from the examples.** `.env.example` holds
placeholder API keys that the production Gateway would receive. Both compose
files mark the env files optional so a fresh checkout still starts and stops.
- **Support bundles export no secrets** and show an external runtime home as
`{DEER_FLOW_HOME}`.
## Start, stop, clean
- **Validate before you stop anything.** `serve.sh` resolves the bind host and
config first, so a bad value cannot tear down a running stack.
- **`down` skips secret and permission checks.** Permission damage in the runtime
home must not prevent teardown.
- **`make clean` deletes the runtime home**, which the compose stacks mount. It
refuses while the Gateway container runs, and it stops sandbox containers
before the delete because their thread mounts live in that tree.
- **Match container names exactly.** Docker's `name=` filter is a substring match.
`cleanup-containers.sh` verifies the anchored prefix afterwards, so it cannot
remove another project's container.
- **Runtime commands use `uv run --no-sync`**, which keeps installed extras such
as database drivers.
- **Browser sessions need a single Gateway worker process.** They are
process-local, so launchers keep `WEB_CONCURRENCY` unset or `1`.
- **The multi-instance dev harness keeps IM channels disabled** unless asked.
Credentials saved through the UI could otherwise connect a real bot later.
## Checks and analysis
- **Skill review waivers take effect from the base revision only.** The head
manifest is validated but cannot authorize a finding in its own pull request.
Blockers are never waivable.
- **`detect-blocking-io` is a static approximation.** It resolves calls by name
inside one file and over-reports on purpose. The strict gate is the runtime
suite `make test-blocking-io`; `scan_changed_blocking_io.py` limits the static
findings to a diff.
- **`detect-thread-boundaries --runtime-config` imports configured tools and
models.** It does not call models or external services.