Files
MoShiro/AGENTS.md
T
justme d5ebf29e57
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/e2e Pipeline was successful
docs: tighten wording, soften node capability claims, link architecture to code
- Remove the node capability paragraph from README; soften "pure collector"
  and "no self-update" statements in docs, AGENTS.md and READMEs
- architecture.md: drop scalability goals, design decisions and open items;
  add a component-to-code table and code links
- Replace rhetorical contrasts in security docs with direct statements
- AGENTS.md: add project mental model, change map and writing style rules
2026-10-21 06:52:01 +08:00

7.9 KiB

Agent Instructions

MoShiro is a self-hosted network path quality monitor. Probes (home broadband) and Agents (public VPS) run active measurements and record raw per-packet and per-event data. The Backend stores it, derives metrics, scores lines per service model, and serves a REST/SSE API to two web apps. Documentation is in Chinese under docs/; source comments are mostly Chinese too. README.md is the entry point.

Mental model

Term Meaning
Probe, Agent Collector processes (NativeAOT, BCL only). The Probe always dials the Agent; both dial the Backend over wss
Line One (Probe, Agent) pair, per IP family. Id <agent_id>~<probe_id>, IPv6 adds ~ipv6; series key line:<probe_id>
Kind A declared measurement method (udp_echo, tcp_echo, connect, ...) composed from building blocks. Defined once in MoShiro.Protocol/Catalog/Kinds
RawChunk Self-describing columnar block, cut every 10 s, appended to segment files. The Backend never trusts node-reported statistics
Metric, Model MetricDef is a one-line declaration over accumulators; models score metrics at query time. Both are recomputable from raw data
Plan A sequence of on-demand test phases (for example hy2_ladder). Exists only in the Backend (Application/Tests/Plans.cs)
Fleet Product-agnostic node framework under backend/fleet/ (identity, enrollment, RPC, link, outbox, state sync)
Operator set Passkey-signed trust root. Nodes pin its genesis fingerprint and owner at install time and verify the chain themselves

Invariants (violations fail the build or review)

  • Node processes are kept to measurement and reporting by build-time restrictions: process start, dynamic loading, HttpClient, and file writes outside Fleet.Hosting.ConfigStore are banned (backend/BannedSymbols.Node.txt). Capabilities such as updates or command execution are not part of the core; adding or changing one needs a design review against docs/security/security.md.
  • backend/fleet/** must not reference MoShiro.* (ArchitectureTests). MoShiro.Measurement contains no service concepts such as REALITY or Hysteria2.
  • Every RPC method is declared in a method table (FleetMethodTable, MoShiroMethodTable) with direction, type and roles. Add the declaration before the handler.
  • Backend.Api must not reference Storage. Error-code to HTTP mapping happens once, in the Api layer.
  • Server-sent parameters pass ParamSpec validation and then the node-local hard limits (BudgetGuard). Never bypass either.
  • Public API responses contain no IP, city or ASN.
  • Code style is enforced at build time (.editorconfig, BannedSymbols.txt, warnings as errors). Details in docs/dev/coding-style.md.

Where to change what

Task Location
New measurement method Kind declaration in backend/shared/MoShiro.Protocol/Catalog/Kinds; new building block only if needed in MoShiro.Measurement/Blocks plus BlockCatalog
New metric MetricDef in backend/src/MoShiro.Backend.Analysis/Metrics, add to MetricRegistry.All and a preset if shown
New service model Analysis/Models
New RPC method MoShiro.Protocol/Rpc (params, MoShiroMethodTable), then router.On(...) in AgentApp or ProbeApp; Backend-side handlers register in Backend.Gateway (FleetGateway)
New REST endpoint Backend.Api/Public or Admin (typed results, operationId, capability), contract DTO in Api/Contracts, then regenerate backend/openapi/v1.json and web types
New capability Capability constants in Backend.Application/Auth/Capabilities.cs; every /api/admin endpoint must declare one
Schema change Append a migration in Storage.Sqlite/Schema.cs and bump CurrentVersion
Install or update behaviour packaging/ (install scripts, Quadlet, compose, updater) and docs/ops/deployment.md
Web UI web/display (anonymous read-only), web/admin, shared code in web/shared. Colors only in web/shared/theme/tokens.css

Documentation

Index: README.md. Prefer the code and backend/openapi/v1.json when they disagree with a document, and fix the document. Update docs in the same change as behaviour: docs/design (architecture, protocol, measurement, analysis, storage, query), docs/security, docs/api, docs/ops, docs/dev, and docs/roadmap.md for unimplemented work. Do not record dates or change history in docs.

Writing style for docs, READMEs, comments and commit messages (the stop-slop skill lists the patterns in detail; it is written for English, the same rules apply to Chinese):

  • State the fact directly. Drop "not X but Y" contrasts, negation lists, rhetorical setups, and aphorisms that read like pull-quotes.
  • Name the actor. Prefer "the Agent rejects the task" over "the task is rejected".
  • No filler openers ("it is worth noting"), no closing summaries, no adverbs doing emphasis. Avoid bold for emphasis.
  • Do not claim absolutes ("never", "always", "cannot") unless the code or a build-time check enforces it. Describe current behaviour and mark planned work as planned.
  • Give concrete names, paths, values and commands instead of general statements.

Workspace safety

  • Inspect git status before editing. Preserve existing uncommitted changes; do not reset, clean, stash, or commit unrelated files.
  • main is the only working branch. Commit to it directly; use a pull request when review is required.
  • Never commit credentials, API keys, registry passwords, or generated runtime data. CI credentials are Woodpecker secrets (zot_secret, gitea_token, release_signing_key).
  • The release signing private key must not enter the repository or the panel. Only the public key under packaging/update/ is versioned.

Build and test

Requirements: .NET SDK 10 (pinned by global.json) and Node.js with npm. NuGet versions are centralized in Directory.Packages.props.

Task Command
Build all .NET projects dotnet build MoShiro.slnx -c Release
Backend tests cd backend && dotnet test --solution MoShiro.slnx -c Release
Run Backend cd backend && dotnet run --project src/MoShiro.Backend -- --urls http://localhost:5000
Web dependencies and build npm ci --prefix web && npm run build --prefix web
Web dev servers npm run dev --prefix web (ports are set in the Vite configs)
Style check npm run lint:css --prefix web
Regenerate API types npm run gen:api --prefix web

First run of the Backend prints a claim code in its log; the admin UI asks for it. Slow end-to-end tests carry [Trait("Category", "Slow")]. After changing API contracts, update backend/openapi/v1.json and regenerate the web types. Run only the validation the task requires; do not start a full tag or release build unless requested.

CI and releases

Triggers, tags and image paths are defined in .woodpecker/*.yml and docs/ops/deployment.md. Verify them there before changing or describing them. The rules below are the stable contract.

  • Every push to main runs the fast Backend tests and the web build. Both must pass before images are published.
  • A commit message containing [CI] builds and pushes development images. [CI SKIP] skips the pipeline; [SKIP TESTS] skips only the Backend tests. Slow end-to-end tests run after image publication and do not block it.
  • A tag vMAJOR.MINOR.PATCH runs the full cross-platform release pipeline. No version-bump commit is needed.
  • Versions are produced by ci/version.sh. The <Version> in backend/Directory.Build.props and the version in web package.json files are placeholders (0.0.0-dev) and must not be edited.
  • Development images use the moshiro-dev/ repository path and release images use moshiro/. A development build must never overwrite a release tag such as latest.
  • Release manifests are registered at /api/release/offer, which requires no token because the panel verifies the signature.