Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
1b3794c
fix(monitoring): track runtime-production heartbeat branch (#315)
Pigbibi Sep 22, 2026
8c24458
fix: isolate Binance monitor identity (#316)
Pigbibi Sep 23, 2026
c128eff
fix: stop blanket personal review requests
Pigbibi Sep 28, 2026
2a8460f
build(deps): bump QuantStrategyLab/QuantRuntimeSettings/actions/publi…
dependabot[bot] Sep 28, 2026
ac0b7fe
build(deps): bump QuantStrategyLab/QuantRuntimeSettings/actions/publi…
dependabot[bot] Sep 28, 2026
f1fedcd
feat(homepage): add pinned read-only Spot and Earn facts publisher (#…
Pigbibi Oct 2, 2026
854e8dc
build(deps): bump urllib3 from 2.7.0 to 2.8.0
dependabot[bot] Oct 2, 2026
a7bf700
fix: bind companion account facts to successful parent runtime (#322)
Pigbibi Oct 2, 2026
4ca436a
fix: qualify terminal reports from the protected production workflow …
Pigbibi Oct 2, 2026
0ce49bc
fix: install uv in isolated account facts job
Pigbibi Oct 2, 2026
e46bda2
Merge pull request #325 from QuantStrategyLab/codex/binance-account-f…
Pigbibi Oct 2, 2026
30984af
fix: use workflow identity instead of dynamic run title
Pigbibi Oct 2, 2026
2e709fa
Merge pull request #327 from QuantStrategyLab/codex/binance-run-title…
Pigbibi Oct 2, 2026
4ea1cb3
fix: qualify read-only identity and serialized reports
Pigbibi Oct 2, 2026
2a11828
Merge pull request #328 from QuantStrategyLab/codex/binance-report-id…
Pigbibi Oct 2, 2026
bf5f731
fix: distinguish private-safe spot response failures (#329)
Pigbibi Oct 2, 2026
12e2250
fix: preserve valid Unicode wallet asset codes (#330)
Pigbibi Oct 2, 2026
d9fe471
Classify private-safe account-facts publish failures (#331)
Pigbibi Oct 2, 2026
ab4f415
Read receiver readiness from the existing protected runner (#332)
Pigbibi Oct 2, 2026
0182b14
fix: identify isolated account facts HTTP client explicitly (#333)
Pigbibi Oct 2, 2026
2696cce
Add native USDT wallet valuation to read-only account facts (#334)
Pigbibi Oct 2, 2026
16ecd71
feat: include Binance native API product type in account facts
Pigbibi Oct 3, 2026
3e2fae5
Merge pull request #335 from QuantStrategyLab/codex/binance-provider-…
Pigbibi Oct 3, 2026
5975774
fix: report only validated Binance product type category
Pigbibi Oct 3, 2026
ab7daec
Merge pull request #336 from QuantStrategyLab/codex/binance-product-t…
Pigbibi Oct 3, 2026
ff7bcb2
feat: add inactive interval source receipt candidate
Pigbibi Oct 4, 2026
f679ec3
Merge pull request #337 from QuantStrategyLab/codex/interval-source-r…
Pigbibi Oct 4, 2026
38e5033
feat: add inactive retained interval reader prerequisite
Pigbibi Oct 4, 2026
d5a2c70
Merge pull request #338 from QuantStrategyLab/codex/interval-receipt-…
Pigbibi Oct 4, 2026
fe2f9ea
Fence bound source sessions and retain verified interval receipts opt-in
Pigbibi Oct 4, 2026
9e97c4a
Scope writer inventory to owned source instead of CI dependencies
Pigbibi Oct 4, 2026
db87064
Merge pull request #339 from QuantStrategyLab/codex/bound-source-sess…
Pigbibi Oct 4, 2026
329ed5a
docs: qualify the interval receipt reader candidate
Pigbibi Oct 5, 2026
d434bf9
Merge pull request #340 from QuantStrategyLab/codex/reviewed-wave1-bi…
Pigbibi Oct 5, 2026
f591de0
build(deps): bump QuantStrategyLab/QuantRuntimeSettings/actions/publi…
dependabot[bot] Oct 5, 2026
562d0d6
build(deps): bump werkzeug from 3.1.8 to 3.1.9
dependabot[bot] Oct 5, 2026
fe1f229
build(deps): bump QuantStrategyLab/QuantRuntimeSettings/actions/publi…
dependabot[bot] Oct 5, 2026
a35c0ea
build(deps): bump multidict from 6.7.1 to 6.9.1
dependabot[bot] Oct 6, 2026
cca4ee6
fix(notifications): honor zero BTC status report interval (#345)
Pigbibi Oct 6, 2026
12c9937
docs: rewrite governance templates into human-readable prose (#346)
Pigbibi Oct 6, 2026
396cb03
删除未使用的 Codex App 审查脚本 (#349)
Pigbibi Oct 7, 2026
a011e56
Use scoped GitHub App tokens for authority maintenance (#350)
Pigbibi Oct 7, 2026
1aa5b39
fix: separate bound account facts reads from Runtime success
Pigbibi Oct 8, 2026
6ccdd67
fix: retain the protected branch for direct account reads
Pigbibi Oct 8, 2026
d89f9ae
Merge pull request #352 from QuantStrategyLab/codex/binance-facts-dir…
Pigbibi Oct 8, 2026
c986fc7
Schedule gated daily read-only Binance account facts refresh
Pigbibi Oct 8, 2026
34662b2
Merge pull request #354 from QuantStrategyLab/codex/binance-facts-ref…
Pigbibi Oct 8, 2026
5b1079a
fix: preserve valid deployment observations independently of alerts (…
Pigbibi Oct 8, 2026
f1b54db
fix: bound independent runtime scheduler diagnostics
Pigbibi Oct 8, 2026
5bff53b
Merge pull request #356 from QuantStrategyLab/codex/binance-scheduler…
Pigbibi Oct 8, 2026
94f86fb
fix: observe scheduler independently in lifecycle monitoring
Pigbibi Oct 8, 2026
c34d5d6
Merge pull request #357 from QuantStrategyLab/codex/binance-scheduler…
Pigbibi Oct 8, 2026
9f07699
fix: use available python3 on scheduler observer host (#358)
Pigbibi Oct 8, 2026
9d4c75d
refactor(b09): bind trend universe to RunContext during execute_cycle…
Pigbibi Oct 9, 2026
077a64c
refactor(b09): mount STRATEGY_RUNTIME onto RunContext during cycles (…
Pigbibi Oct 9, 2026
b5226b8
refactor(b09): drop bound-cycle STRATEGY_RUNTIME module fallback (#361)
Pigbibi Oct 9, 2026
86101d5
fix(ops): skip Runtime heartbeat alert when main.yml is disabled
Pigbibi Oct 9, 2026
e75c6e5
Merge pull request #362 from QuantStrategyLab/ops/runtime-heartbeat-d…
Pigbibi Oct 9, 2026
eb7dbed
feat(execution): pin QPK #657 and consult T2/T3 on UNKNOWN deny (N13)…
Pigbibi Oct 9, 2026
9e5495f
ops: read-only TG_TOKEN bot identity check (getMe id/username only) (…
Pigbibi Oct 10, 2026
0d55203
ops: bot identity check reads repo-level TG_TOKEN without binance-run…
Pigbibi Oct 10, 2026
fc01622
sync: bring runtime-production #347/#348/#351/#353 into main
Pigbibi Oct 11, 2026
44a0cd6
Merge pull request #367 from QuantStrategyLab/sync/rp-into-main
Pigbibi Oct 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
* @Pigbibi
# Blanket personal review assignment is intentionally disabled.
# Do not automatically request a personal review for every pull request:
# withdrawing a request after creation cannot prevent its notification.
# Required CI and investment/runtime authorization remain independently enforced.
48 changes: 48 additions & 0 deletions .github/workflows/diagnose-account-facts-receiver.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Diagnose Binance Account Facts Receiver

"on":
workflow_dispatch:

permissions:
contents: read

concurrency:
group: binance-account-facts-readonly
cancel-in-progress: false

jobs:
readiness:
if: github.event_name == 'workflow_dispatch' && github.repository == 'QuantStrategyLab/BinancePlatform' && github.ref == 'refs/heads/main'
runs-on: self-hosted
timeout-minutes: 2
environment: binance-runtime
steps:
- name: Checkout the exact dispatch revision
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
ref: ${{ github.sha }}
persist-credentials: false

- name: Require the exact current main revision
shell: bash
run: |
set -euo pipefail
if [[ "$GITHUB_EVENT_NAME" != "workflow_dispatch" || \
"$GITHUB_REPOSITORY" != "QuantStrategyLab/BinancePlatform" || \
"$GITHUB_REF" != "refs/heads/main" || \
! "$GITHUB_SHA" =~ ^[0-9a-f]{40}$ || \
"$(git rev-parse HEAD)" != "$GITHUB_SHA" ]]; then
echo "receiver_diagnosis_source_unqualified" >&2
exit 1
fi
current_main_sha="$(git ls-remote https://github.com/QuantStrategyLab/BinancePlatform.git refs/heads/main 2>/dev/null | awk 'NF == 2 && $2 == "refs/heads/main" { print $1 }')"
if [[ ! "$current_main_sha" =~ ^[0-9a-f]{40}$ || "$current_main_sha" != "$GITHUB_SHA" ]]; then
echo "receiver_diagnosis_main_sha_mismatch" >&2
exit 1
fi

- name: Read receiver readiness once
shell: bash
env:
BINANCE_ACCOUNT_FACTS_SYNC_TOKEN: ${{ secrets.BINANCE_ACCOUNT_FACTS_SYNC_TOKEN }}
run: python3 scripts/diagnose_binance_account_facts_receiver.py
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ jobs:

- name: Publish disabled host observation
if: ${{ steps.disabled-host.outputs.publish_ready == 'true' }}
uses: QuantStrategyLab/QuantRuntimeSettings/actions/publish-runtime-target-lifecycle@bbacba04baccbca91e4ba59c4dcaf460847e29f7
uses: QuantStrategyLab/QuantRuntimeSettings/actions/publish-runtime-target-lifecycle@f2597e8bfb25881242b13145cb5f42d06ba3476c
with:
source-id: binance.runtime-target-lifecycle
target-id: ${{ steps.disabled-host.outputs.target_id }}
Expand Down
50 changes: 50 additions & 0 deletions .github/workflows/notify-bot-identity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Notify Bot Identity (read-only)

# Resolves the Telegram token the Binance runtime would use (main.yml deploy job:
# secrets.TG_TOKEN, a repo-level secret; binance-runtime only holds other secrets
# and is restricted to runtime-production, so this job does not bind it) to its public bot id/username via
# getMe, and compares it with the unified QSL资产管家 bot (8334367951).
# Prints only bot id / username; never prints token or chat id; sends no message;
# does not re-enable main.yml or change any secret.
on:
workflow_dispatch:

permissions:
contents: read

jobs:
identity:
name: TG_TOKEN bot identity (read-only)
runs-on: ubuntu-latest
timeout-minutes: 5
env:
TG_TOKEN: ${{ secrets.TG_TOKEN }}
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
EXPECTED_BOT_ID: "8334367951"
steps:
- name: Resolve bot identity
run: |
python3 - <<'PY'
import json, os, urllib.request
expected = int(os.environ["EXPECTED_BOT_ID"])
out = []
for key in ("TG_TOKEN", "TELEGRAM_TOKEN"):
token = (os.environ.get(key) or "").strip()
if not token:
out.append({"env": key, "status": "absent"})
continue
try:
with urllib.request.urlopen(f"https://api.telegram.org/bot{token}/getMe", timeout=15) as r:
body = json.loads(r.read().decode("utf-8"))
res = body.get("result") or {}
out.append({"env": key, "status": "ok" if body.get("ok") else "getme_not_ok",
"bot_id": res.get("id"), "bot_username": res.get("username"),
"same_bot_as_unified": res.get("id") == expected})
except Exception as exc: # noqa: BLE001
out.append({"env": key, "status": f"getme_failed:{type(exc).__name__}"})
text = json.dumps({"runtime_token_env": "TG_TOKEN", "expected_bot_id": expected, "tokens": out},
ensure_ascii=False, indent=2)
print(text)
with open(os.environ["GITHUB_STEP_SUMMARY"], "a", encoding="utf-8") as fh:
fh.write("## Binance notify bot identity\n\n```json\n" + text + "\n```\n")
PY
90 changes: 90 additions & 0 deletions .github/workflows/refresh-binance-account-facts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Refresh Binance Account Facts

"on":
schedule:
- cron: "17 6 * * *"
workflow_dispatch:
inputs:
enabled:
description: "Run one read-only account-facts refresh; the repository gate must also be enabled."
required: true
type: boolean
default: false

permissions:
contents: read

jobs:
dispatch-account-facts-read:
if: >-
github.repository == 'QuantStrategyLab/BinancePlatform' &&
github.ref == 'refs/heads/main' &&
vars.BINANCE_ACCOUNT_FACTS_REFRESH_ENABLED == 'true' &&
(github.event_name == 'schedule' ||
(github.event_name == 'workflow_dispatch' && inputs.enabled == true))
runs-on: ubuntu-latest
timeout-minutes: 2
permissions:
actions: write
contents: read
steps:
- name: Dispatch the fixed read-only account-facts workflow
shell: python
env:
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_TOKEN: ${{ github.token }}
run: |
import json
import os
import sys
from urllib.error import HTTPError, URLError
from urllib.request import HTTPRedirectHandler, Request, build_opener

api_url = os.environ.get("GITHUB_API_URL", "").rstrip("/")
token = os.environ.get("GITHUB_TOKEN", "")
if not api_url or not token:
print("account_facts_dispatch_not_configured", file=sys.stderr)
raise SystemExit(1)

url = (
f"{api_url}/repos/QuantStrategyLab/BinancePlatform/actions/"
"workflows/binance-account-facts.yml/dispatches"
)
payload = {
"ref": "runtime-production",
"inputs": {"enabled": True, "source_mode": "direct_read"},
}
request = Request(
url,
data=json.dumps(payload).encode("utf-8"),
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"X-GitHub-Api-Version": "2022-11-28",
},
method="POST",
)

class RejectRedirects(HTTPRedirectHandler):
def redirect_request(self, _request, _file, _code, _message, _headers, _url):
return None

opener = build_opener(RejectRedirects)

try:
with opener.open(request, timeout=30) as response:
if response.status not in (200, 204):
print("account_facts_dispatch_outcome_unknown", file=sys.stderr)
raise SystemExit(1)
except HTTPError as error:
if 400 <= error.code < 500:
print("account_facts_dispatch_rejected", file=sys.stderr)
else:
print("account_facts_dispatch_outcome_unknown", file=sys.stderr)
raise SystemExit(1)
except (URLError, TimeoutError, OSError):
print("account_facts_dispatch_outcome_unknown", file=sys.stderr)
raise SystemExit(1)

print("account_facts_dispatch=accepted")
94 changes: 9 additions & 85 deletions .github/workflows/runner-scheduler-diagnostics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,91 +11,15 @@ concurrency:
cancel-in-progress: false

jobs:
inspect:
observe:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: self-hosted
timeout-minutes: 10
timeout-minutes: 3
steps:
- name: Inspect scheduler configuration
shell: bash
run: |
set -euo pipefail
- name: Checkout reviewed main source
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
persist-credentials: false

redact() {
sed -E \
-e 's/github_pat_[A-Za-z0-9_]+/[REDACTED_GITHUB_TOKEN]/g' \
-e 's/gh[pousr]_[A-Za-z0-9_]+/[REDACTED_GITHUB_TOKEN]/g' \
-e 's/(Authorization:[[:space:]]*Bearer[[:space:]]+)[A-Za-z0-9_.-]+/\1[REDACTED]/g' \
-e 's/(x-access-token:)[^@[:space:]]+/\1[REDACTED]/g' \
-e 's/((TOKEN|SECRET|KEY|PASSWORD)[A-Z0-9_]*[[:space:]]*=[[:space:]]*)[^[:space:]]+/\1[REDACTED]/g'
}

section() {
printf '\n===== %s =====\n' "$1"
}

section "host"
{
date -u
hostname
id
pwd
uname -a
} | redact

section "ubuntu crontab"
crontab -l 2>&1 | redact || true

section "root crontab"
sudo -n crontab -l 2>&1 | redact || true

section "systemd timers"
systemctl list-timers --all 2>&1 | redact || true

section "matching systemd units"
systemctl list-units --all 2>&1 | grep -Ei 'binance|quant|github|dispatch|runtime' | redact || true

section "cron and systemd files"
find /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/systemd/system -maxdepth 2 -type f -print 2>/dev/null \
| sort \
| grep -Ei 'binance|quant|github|dispatch|runtime|cron|timer|service' \
| redact || true

section "candidate dispatch files"
find /home/ubuntu /usr/local/bin /opt -maxdepth 6 \
\( -path '*/.git' -o -path '*/_work' -o -path '*/node_modules' \) -prune -o \
-type f \
\( -name '*.sh' -o -name '*.py' -o -name '*.service' -o -name '*.timer' -o -name '*.env' -o -name 'crontab' \) \
-print 2>/dev/null \
| sort \
| grep -Ei 'binance|quant|github|dispatch|runtime|cron' \
| redact || true

section "dispatch content matches"
find /home/ubuntu /usr/local/bin /opt /etc/cron.d /etc/systemd/system -maxdepth 8 \
\( -path '*/.git' -o -path '*/_work' -o -path '*/node_modules' \) -prune -o \
-type f \
\( -name '*.sh' -o -name '*.py' -o -name '*.service' -o -name '*.timer' -o -name '*.env' -o -name '*.conf' -o -name 'crontab' \) \
-print 2>/dev/null \
| while IFS= read -r file; do
if grep -IlE 'actions/workflows/main\.yml/dispatches|workflow_dispatch|QuantStrategyLab/BinancePlatform|binance-quant|binancequant' "$file" >/dev/null 2>&1; then
printf '%s\n' "$file"
fi
done \
| sort \
| head -200 \
| redact || true

section "dispatch script redacted"
if [ -f /home/ubuntu/binance-quant/ops/dispatch-runtime.sh ]; then
sed -n '1,240p' /home/ubuntu/binance-quant/ops/dispatch-runtime.sh | redact
else
echo "dispatch-runtime.sh not found"
fi

section "dispatch env keys"
if [ -f /home/ubuntu/.config/binance-platform/dispatch.env ]; then
sed -E 's/(^[[:space:]]*(export[[:space:]]+)?[A-Za-z_][A-Za-z0-9_]*=).*/\1[REDACTED]/' \
/home/ubuntu/.config/binance-platform/dispatch.env | redact
else
echo "dispatch.env not found"
fi
- name: Observe scheduler state
run: python3 -m scripts.runtime_scheduler_probe
1 change: 1 addition & 0 deletions .github/workflows/runtime-heartbeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jobs:
env:
RUNTIME_HEARTBEAT_NAME: BinancePlatform Runtime
RUNTIME_HEARTBEAT_WORKFLOW: main.yml
RUNTIME_HEARTBEAT_BRANCH: ${{ vars.RUNTIME_HEARTBEAT_BRANCH || 'runtime-production' }}
RUNTIME_HEARTBEAT_LOOKBACK_HOURS: ${{ inputs.lookback_hours || vars.RUNTIME_HEARTBEAT_LOOKBACK_HOURS || '2.5' }}
RUNTIME_HEARTBEAT_EXPECTED_INTERVAL_HOURS: ${{ vars.RUNTIME_HEARTBEAT_EXPECTED_INTERVAL_HOURS || '1' }}
RUNTIME_HEARTBEAT_MAX_CONSECUTIVE_MISSES: ${{ vars.RUNTIME_HEARTBEAT_MAX_CONSECUTIVE_MISSES || '2' }}
Expand Down
Loading
Loading