agent_nodes gains probe_only; getConfig always serves the flag and withholds the sing-box payload (null config, empty hash) for flagged nodes while probe tasks, fast interval, stat iface and update intents ride as usual. The agent gates both core branches when the local agent.json preset or the master flag is on, retires a running core once (best-effort tail flush, switchover bookkeeping untouched so turning the flag off self-heals through the existing hash-current-but-not-running path), and makes the traffic cycle an explicit no-op. Panel: node create/update accept probeOnly, the node view overlays it from the binding, the node form gains a switch (carried into the generated install command), the list shows a probe-only tag in the core-version cell, and install-agent.sh --probe-only writes the preset, skips the core download/self-check and inherits the flag on no-arg reruns.
- 0: sing-box gen overrides fragment listen/port from the inbound row
(empty listen -> "::"), Update/Add recompute the stored fragment;
non-loopback E2E against the real core binary.
- 1: agent fetches the sing-box core from the Gitea release when
missing, self-checks it, and only then latches the switch.
- 2: node list shows the sing-box core version (heartbeat field,
persisted on the node row), xray version as fallback.
- 3: public-page fallback returns 404 to anonymous visitors when the
page is disabled.
- 4: settings restart hint bar removed, dead i18n keys cleaned.
- 5: two PUT calls missing JSON headers fixed (audit: only those two),
batch probe-task creation endpoint + UI.
- 6: cf-probe retirement card and coverage pipeline removed.
- 7: generated vless links no longer carry spx (panel export + sub);
parser still accepts spx; golden fixtures updated.
- probe batch: dedicated probe settings tab (public-page settings,
tasks, per-node meta), retention_days editable, per-node traffic
calibration + stat-interface pinning, runtime metrics split into a
lightweight fast report (default 3s, 1-60s adjustable).
- 8: sing-box core processes start with GOMEMLIMIT=32MiB, GOGC=50.
- 9: dead /getTwoFactorEnable docs entries removed (frontend call and
contract entry already gone at base; verified by grep).
- master getConfig serves singbox_config only; xray payload retired
(build failure is a hard 500, agent keeps its current state)
- agent: singbox_config arrival is the switch signal — flush xray
tail traffic, stop xray, activate sing-box; activation failure
restarts xray from the last payload and retries next poll; a
legacy master (no sing-box keys) keeps the xray path untouched
- sing-box log rotation: 8 MiB copy-truncate with one .1 kept,
checked on the traffic cycle
- install-agent.sh: xray/geo downloads and checks removed, agent
binary now from the V2.0.0 release, self-check is sing-box
binary + check on the live config
- display version default 2.0.0 (master V2.0.0 / agent A2.0.0)
Agent consumes singbox_config alongside xray: candidate->check->
flush->swap activation with .previous rollback, wire-level v2ray_api
stats client with NexusGate epoch discipline (mid-query flip voids
the round, new epoch counts in full, agent-first snapshot baselines),
access-log online tracker (authenticated-connection lines, ANSI-safe,
merged with snapshot-active users), per-core traffic baselines with
the sing-box one carrying its epoch. install-agent.sh installs the
self-built sing-box v1.13.21 next to xray (xray/geo removal deferred
to the B5 switchover). Env-gated real-core E2E covers vless-reality,
ss2022, mixed, trojan and the forwarding leg end to end; hysteria2 is
probe-gated (sandbox blocks UDP replies) and stays a B5 pilot item.
- probe package: probe_ping_task/probe_ping_node tables; task CRUD
with hub save semantics (id high-water, base-diff assignment,
64-per-agent crowding refusal, auto_join cap); filing with
assignment-gated insert; PingHistory weighted-median chart read
over minute+hour tiers; auto-join on first Record (ensureRows).
- controller: /panel/api/agent/probe-tasks* management endpoints
(node id space, hub validation chain verbatim); series=ping now
serves real rows from probe.PingHistory; heartbeat ingests
probeResults (missing latency skipped, batch capped); config
response carries probe_tasks (always present, empty = clear).
- agent: per-task probe loops (immediate first probe, ticker,
900ms resolve/dial budgets, <=3 addresses, resolve overrun = no
sample), result buffer drained on heartbeat and requeued on
failure; task set applied before the config-hash early return.