Guidance for AI coding agents working in this repository. Keep changes minimal, follow the patterns already in the codebase, and verify with the commands below before submitting.
Normative task-card rules are defined in
docs/plan/plan-template.md, currently v2.5
(effective 2026-10-15): ER-* execution gates, GC-* engineering constraints, and
G-01–G-13 granularity/release boundaries. Follow its incremental migration
policy for existing plans; this file is a synchronized entry point, not a
separate waiver. G-13 permits only a predeclared, reviewed aggregate of 2–3
independent code defects actually blocking strict gates in one unpublished
repair frontier; it preserves each card's behavior axis and full final C/D.
- Name:
mega2(single Cargo package: libmega2_core+ binaries, seeCargo.toml). - Edition: Rust 2024.
- Purpose: Mono‑repo / Git hosting + service engine. Ports and extends
several subsystems originally from the Mega project (notably
callistoentities andjupiterstorage/migration). - Entry point:
src/main.rs→cli::parse(None). - Config: TOML loaded from
config/config.toml(override via--configflag orMEGA_CONFIGenv var). Loader lives insrc/config/loader.rs.
- Language: Rust 2024 (stable toolchain).
- CLI:
clapv4 (derive + builder), subcommands registered insrc/commands/mod.rs(builtin()/builtin_exec()). - Async runtime:
tokio(full features). - HTTP / API:
axum0.8 +tower-http, OpenAPI viautoipa+ Swagger UI. - Storage / DB:
sea-orm1.1 (Postgres + SQLite,runtime-tokio-rustls) andsea-orm-migration. Entities are insrc/callisto/. - Cache / queue:
redis(withconnection-manager). - Auth / policy:
cedar-policy(schema insrc/contract/policy/mega.cedarschema, policies insrc/contract/policy/mega_policies.cedar). - Crypto / TLS:
rustls,ring,openssl,ed25519-dalek,rsa,secp256k1,pgp. Vault‑style PKI/secret engine via thelibvaultcrate (crates.io0.3.0, featuresstorage_pg+crypto_adaptor_openssl) and the mega2 integration layer (src/contract/vault/). The RustyVault sources used to be vendored undersrc/vault/; that module was removed on 2026-08-21 (docs/plan/plan-20260820.md), so import library types fromlibvault::*. - Email:
lettre(rustls + tokio). - Object storage: inlined
src/orbit_api/(traits/config) andsrc/orbit/(object_store backends). Built viacrate::orbit::factory::ObjectStorageFactoryfromsrc/jupiter/storage/object_storage.rs::build_object_storage. - Allocator:
jemallocon non‑Windows,mimallocon Windows (configured insrc/main.rs). - Logging:
tracing+tracing-subscriber+tracing-appender(hourly rolling file undermega_cache()/logs, or stdout whenlog.print_std = true).
Run these from the repo root (the agent's shell already starts there).
| Task | Command |
|---|---|
| Build (release-ish) | cargo build |
| Build incl. tests | cargo build --tests |
| Run all tests | cargo test |
| Run one test | cargo test --test <name> or cargo test <substring> -- --nocapture |
| Format | cargo fmt --all |
| Lint | cargo clippy --all-targets -- -D warnings (when used) |
| Run the binary | cargo run -p mega2 -- --config config/config.toml <subcommand> |
| HTTP service example | cargo run -p mega2 -- --config config/config.toml service http --host 0.0.0.0 -p 9000 |
Invariants the build must hold (verified in prior sessions):
cargo buildMUST produce 0 errors and 0 warnings.cargo build --testsMUST produce 0 errors and 0 warnings.- Never silence warnings by adding broad
#[allow(...)]on items you just touched without a reason — the crate‑level#![allow(dead_code)]insrc/lib.rsis intentional (large pub API surface ported from Mega); do not narrow or remove it without a plan to clean the dead items.
Any change to the codebase MUST satisfy all three of the following gates.
These are not optional — do not submit a change until each one is green.
Use the exact commands below (do not substitute simpler variants such as
cargo fmt --all --check or cargo clippy -- -D warnings):
-
Formatting (nightly, check‑only):
cargo +nightly fmt --all --check
Must report no diff. If it does, run
cargo +nightly fmt --allto apply formatting and re‑run the check until clean. The nightly toolchain is required becauserustfmt.tomlmay enable unstable options. -
Lints (all targets, all features, warnings denied):
cargo clippy --all-targets --all-features -- -D warnings
Must exit with 0 warnings, 0 errors. Do not bypass a clippy lint with a blanket
#[allow(...)]; prefer fixing the underlying code. When an allow is genuinely required (e.g. a deliberate API name that tripsclippy::wrong_self_convention), scope it to the smallest possible item and add a brief rationale. -
Tests (with project test env loaded):
source .env.test && cargo test --all
Must finish with all tests passing (0 failures, 0 errored). The
.env.testfile provides DB / cache / service endpoints the test suite expects; do not skip sourcing it. Do not weaken or#[ignore]tests to make this gate pass — fix the root cause.
If .env.test is missing in your environment, stop and ask before
submitting; do not silently fall back to running cargo test --all
without it.
Cargo.toml # package `mega2` (lib `mega2_core` + [[bin]])
config/config.toml # default runtime config (TOML)
src/
├── main.rs # `mega2` binary entry (allocator + CLI dispatch)
├── lib.rs # library root; declares top-level modules
├── cli.rs # clap parsing, log init, ctrlc handler
├── orbit_api/ # object-storage contract (traits, config, errors)
├── orbit/ # object_store backends (adapter, factory)
├── bin/ # auxiliary binaries (e.g. migrate_local_to_s3)
├── commands/ # subcommand registry (builtin / builtin_exec)
├── common/ # error types (MegaError/MegaResult), utils
├── config/ # config loader, profiles, SecretRef, hot reload
├── api/ # axum HTTP API surface
├── api_model/ # request/response DTOs (utoipa schemas)
├── server/ # HTTP/SSH/etc. server bootstrap
├── callisto/ # sea-orm entity models (one file per table)
├── jupiter/ # storage, service, migration, redis, utils
│ ├── storage/ # *Storage structs (BaseStorage + per-domain)
│ ├── migration/ # sea-orm-migration migrators
│ ├── service/
│ ├── redis/
│ └── tests.rs # `pub mod tests` (cfg(test)) — shared test helpers
├── notification/ # email notifications: dispatcher, triggers, storage
├── email/ # Mailer trait + impls (incl. NoopMailer)
├── contract/
│ ├── policy/ # cedar authz: mega.cedarschema, mega_policies.cedar
│ └── vault/ # PKI / KV / secret engine integration layer over the
│ │ # `libvault` crate (no vendored module since 2026-08-21)
│ └── integration/
│ ├── jupiter_backend.rs
│ └── vault_core.rs # VaultCore, VaultCoreInterface
├── ceres/ context/
tests/ # process-level integration tests (integration_*.rs)
target/ # build artifacts (gitignored)
pub use crate::callisto::*; is re‑exported from lib.rs; importing
callisto entities elsewhere should use crate::callisto::<table> paths.
Object storage public types are available from crate::orbit_api::*; the
concrete backend is built through crate::jupiter::storage::object_storage::build_object_storage
(which calls crate::orbit::factory::ObjectStorageFactory::build).
- Formatting: match
cargo +nightly fmt --alloutput (the same formatter used by the requiredcargo +nightly fmt --all --checkgate). Don't hand‑format around it. - Imports: group by
std→ external crates →crate::(matches the existing files). Avoid wildcarduse crate::*;in library code; wildcards are fine insidemod tests. - Errors: use
crate::common::errors::{MegaError, MegaResult}for application code paths that already use them;anyhow::Resultis used in lower‑level utilities andthiserrorfor new typed errors. Don't mix the three within the same module. - Async: functions returning
Resultshould beasync fn -> Result<T, E>usingtokioruntime. Don't addblock_oninside async contexts. - Logging: use
tracing::{info, warn, error, debug, trace}macros, notprintln!. Structured fields preferred (e.g.info!(path = %p, "loaded")). - DB access: go through the
*Storagetypes insrc/jupiter/storage/rather than callingsea_ormdirectly from API/handler code. - Comments: sparse, English. Match the surrounding density — do not add comments to files that don't already use them.
- Files / modules: snake_case filenames, one module per file,
mod.rsonly for directory module roots.
- Bilingual guide docs: the user-facing guides under
docs/(quick-start,user-guide,configuration,deployment,architecture,contributing) ship in two languages. English is the default file (<name>.md); Chinese lives in the<name>.zh.mdsibling (same convention asREADME.md/README.zh.md). Write the Chinese version first, then translate; both versions must keep identical structure, carry the language switcher line at the top, and cross-link within the same language (zh →.zh.md, en →.md). When you change one language version of a guide, update the other in the same change. - Link, don't copy: facts that have an authoritative home
(
config/config.toml,docs/user-guide.mdfor repository and push behavior,docs/manual/monorepo-init.mdfor initialization layout,docs/deploy-trunk.mdfor trunk operations, anddocs/refactoring/*.mdfor subsystem contracts) are linked, not duplicated. Every relative link in a doc must resolve to a file in the current checkout. - Plan docs under
docs/plan/followdocs/plan/README.mdand the plan templates; they are Chinese-first and unchanged by the bilingual convention above.
sea_ormimports inside tests. There is nocrate::jupiter::sea_ormre‑export. Import traits from the top‑level crate:Forgetting these traits produces misleading errors such asuse sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
email_jobs::Entity is not an iterator.VaultCorepath.src/contract/vault/integration/mod.rsdoes not re‑exportVaultCore. Import it directly from its submodule:use crate::contract::vault::integration::vault_core::{VaultCore, VaultCoreInterface};
- Glob re‑exports / the
vaultname. There is no top-levelmod vault;any more — the vendored RustyVault module was removed on 2026-08-21 and the library comes from thelibvaultcrate.crate::vault::*is not a valid path;rg 'crate::vault' src binshould stay at zero hits. Three different things still share the name, so keep imports explicit:crate::callisto::vaultis the SeaORM entity,crate::contract::vaultis the product integration layer, andlibvault::*is the library itself. - Crate‑level
dead_codeallow.#![allow(dead_code)]inmain.rsis intentional. If you add a new pub API item, you don't need to add per‑item allows; if you remove the crate‑level allow, expect ~70 warnings. - Test DB helpers. Tests requiring a database use
crate::jupiter::tests::test_db_connection(<TempDir path>)followed bycrate::jupiter::migration::apply_migrations(&db, true).await. Reuse these helpers instead of constructing connections by hand. Each call creates amega2_test_<pid>_<n>schema that is dropped with the connection (or when the test thread ends, if something still holds it);test_db_configreturns(DbConfig, TestSchemaGuard)and the guard must stay bound for the whole test (_schema, never_), or the schema is dropped under the connection. - Allocator cfg. Don't touch the
#[global_allocator]blocks inmain.rsunless intentionally changing allocators on a platform. unwrap()in non‑test code. Avoid introducing newunwrap/expecton fallible operations; returnMegaResult/anyhow::Resultinstead. Existing call sites invault/pki.rstest helpers are OK because they are test‑only.
- Implement the command module under
src/commands/<name>.rs. - Register it in
src/commands/mod.rsviabuiltin()(clapCommand) and wire its executor inbuiltin_exec()socli::exec_subcommandfinds it. - The executor signature is
fn(config: Config, args: &ArgMatches) -> MegaResult. - Add unit tests next to the command and, where useful, a CLI parsing test
mirroring the existing ones in
src/cli.rs::tests.
- Generate or hand‑write the entity file under
src/callisto/<table>.rsand add it tosrc/callisto/mod.rs. - Add a migrator under
src/jupiter/migration/and register it in that module's migrator list. - If a new domain storage is needed, add
<domain>_storage.rsundersrc/jupiter/storage/and re‑export fromstorage/mod.rs. - Cover with a
#[cfg(test)] mod teststhat usestest_db_connection+apply_migrationsas shown innotification/dispatcher.rs::tests.
When you change ../megaui sources that affect apps/web, rebuild and
restart the compose website-next service after
the change (do not wait for the user to ask):
./scripts/reload-website-next.shThe script debounces rapid edits (~3s) and runs docker compose build + recreate
in the background. Logs: ${TMPDIR:-/tmp}/mega2-reload-website-next/build.log.
Project hooks in .cursor/hooks.json trigger the same script on megaui file
edits and again on agent stop when a reload was requested.
By default, when an independent plan task card or a release point passes its
A/B local acceptance gates and the required review says PASS, proceed
through C release close-out without waiting for another request. Do not mark
any card Lifecycle=done before its C coverage and all applicable D remote
gates are resolved. VCS is Libra (no git).
- Check version-face parity. For a card with an actual version increment,
bump
Cargo.tomlversionby itsVersion increment(default patch +1) and let the toolchain refreshCargo.lockformega2. - On the final tree (after bump when applicable), run all three gates under
Required Checks Before Submitting Code Changes, plus
cargo buildandcargo build --testswith 0 errors and 0 warnings. libra add <related paths>andlibra commit -s -m "<scope>: <summary>"for that card only; verify the sign-off as required by ER-07.libra push origin mainand verify the remote branch ref. Never--force. If the branch has diverged from origin, stop and report.- For every actual version bump, create and push the matching annotated
v<version>tag, then create its GitHub Release from a manually written release note. These actions are part of C. - Determine D from the live workflow event, ref, path filters, and job
conditions. Record the actual remote result, or the named ER-04 deferral;
then set
Acceptance=completeandLifecycle=done. While an applicable D result is outstanding, useAcceptance=remote-pendingand do not report the card complete. Start the next release card only after this card's C actions finish; release remains serial.
Family, plan-release, repair-aggregate children, and no-release cards inherit
C/D coverage from the carrier named in the card. See docs/plan/plan-template.md
ER-04, ER-07, ER-08, G-12, and G-13 for the full gates, deferral rule, and release
order.
For the explicitly declared G-12 plan-wide release group in
plan-20260920.md, each child completes its A/B
gates, required review, and precise local Libra commit. Until the group's
unique final release point, no child bumps the version, pushes the branch or
tag, or creates a GitHub Release. At that point, check version parity, bump
the patch version exactly once, run the full C checks on the final combined
tree after the bump, push the branch and matching annotated tag, create the
manually written GitHub Release, and resolve the applicable D gates. Children
inherit that final point's C/D coverage and become done/complete only after
the coverage is obtained. The unique final tag's Docker D must actually
succeed; a named ER-04 D deferral does not complete this plan.
For an eligible G-13 repair aggregate, register 2–3 independent implementation
repairs, their actual blocking logs, source cohorts/unpublished baseline, sole publisher,
no-push window, recovery/exit rules, and one release point in REL-* before
further implementation. Actual, mutually isolated Claude and Codex plan reviews
must both explicitly pass its applicability. Each child uses
repair aggregate child of REL-<n>, version/R N/A, and names the point for C/D.
Establish each code cause and repair, pass independent A/B, fmt/clippy and actual
ER-05 review,
and commit precisely locally with ER-07 signature checks and sign-off. No earlier
branch/tag push, Release, or interleaved release slice is allowed. The sole
repair aggregate release point of REL-<n> reviews before its actual patch
bump and executes every C step above on the combined final tree; its tag's
Docker D must actually succeed before any child is done/complete. Unknown
causes, non-reproduction alone, or environment load without a code defect
require ER-03 reassessment/new plan review or a return to G-07 independent
slices. This is not a G-08 family or an EX waiver, and does not replace the G-12
user directive. Published changes recover forward only; existing ER-09/ER-10
budgets, signature, no-force, and test/ignore boundaries remain unchanged.
A terminal evidence-only release card may set Version increment=N/A and
Release write set=N/A only under ER-08: it adds no product behavior and
cannot replace an independently released code card's, family release point's,
G-12 plan-wide group's, or G-13 repair aggregate's versioned release. It skips
the version edit, tag, and GitHub Release while retaining review, the three
gates, builds, precise
commit, push, and actual D-gate mapping. In the G-12 group above, an optional
terminal evidence-only closeout may push evidence, plan-status, and index docs
only after the unique patch release point's Docker D succeeds, without another
version bump, tag, or GitHub Release.
- Do not commit secrets, real tokens, or production
config.tomlvalues. - Do not add new dependencies to
Cargo.tomlwithout confirming they pull their weight (compile time / binary size / license). Prefer reusing what's already vendored (e.g.reqwest,rustls,tokio). - Do not rewrite working modules to "modernize" them; keep diffs focused on the requested change.
- Do not disable or weaken tests (
#[ignore],--skip, deleted asserts) to make a build pass. Fix the root cause or ask. - Do run
cargo buildandcargo build --testsbefore submitting any change that touchessrc/.
Required gates (see Required Checks Before Submitting Code Changes):
-
cargo +nightly fmt --all --check→ no diff. -
cargo clippy --all-targets --all-features -- -D warnings→ 0 warnings, 0 errors. -
source .env.test && cargo test --all→ all tests pass.
Additional sanity checks:
-
cargo build→ 0 errors, 0 warnings. -
cargo build --tests→ 0 errors, 0 warnings. - No stray debug files (
.warnings.log,.output.txt, ad‑hoc scripts) left in the repo root. - No new top‑level
#[allow(...)]other than what already exists.