feat(gsbot)!: faithful Rust/SPARK port — eliminate Python from the fleet#145
Merged
Conversation
gsbot (Garment Sustainability Bot) was the fleet's only Python code (35 .py files) and the source of the 35 `cicd_rules/banned_language_file` critical findings. Python is banned estate-wide with no exceptions; this is a behaviour-preserving rewrite in Rust/SPARK, the sanctioned target. Stack (fleet conventions; gsbot is the fleet's first Discord bot): poise/serenity (prefix commands ↔ discord.py cogs), sqlx+SQLite (SQLAlchemy/Alembic ↔ models + embedded migrations), tracing (colorlog), tokio. Rust/SPARK seam: `src/domain.rs` is the correctness-critical scoring kernel — pure, total functions plus a `#[no_mangle] extern "C"` FFI surface so a verified SPARK/Ada module can be linked in later via the standard Idris2-ABI / Zig-FFI pattern (per the standard: "designed to admit SPARK modules even if it contains none yet"). All callers go through safe wrappers, so substitution is transparent. Faithful behaviour: - Identical env vars/defaults/validation (config.rs ↔ settings.py). - Same schema incl. garment_materials M2M; same scoring (material mean, grade ladder, garment lifespan multiplier + 100 cap, environmental impact averaging, user points/level ratchet, ranks, brand summary). - Every command preserved: names, aliases, argument shapes, point awards (+5/+5/+3/+2 / +5/+7/0 / +5 / 0/0 / admin), embed fields, the `on_command_error` message mapping, presence string. - `!loaddata` fixtures: same 10 materials / 7 garments / 6 brands. - scripts/*.py → 3 bins (gsbot-load-fixtures/-export-data/-backup-db). - Containerfile/docker-compose/Justfile rewritten for Rust (fleet convention: rust builder + debian-slim, non-root); Mustfile recipes (lint/test/fmt) preserved. Verification: `cargo build --all-targets` clean; `cargo clippy --all-targets -- -D warnings` clean; `cargo fmt --check` clean; `cargo test` 18/18 pass (domain 9, models 5, services 4). All Python removed (requirements.txt, setup.py, pytest.ini, alembic.ini, 35 .py) — `banned_language_file` clears for gsbot. Refs hyperpolymath/hypatia#252 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the one deliberate fidelity gap in the Rust/SPARK port: !stats showed a hardcoded `0ms` where the Python bot rendered `bot.latency * 1000`. poise's `ctx.ping()` is the gateway heartbeat latency (serenity `Shard::latency()`), the exact equivalent — zero only until the shard's first heartbeat ack, matching discord.py. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every doc still described the deleted Python bot. Faithfully rewritten from the actual source: poise/serenity + sqlx/SQLite + tracing, the 4 cargo binaries, env vars, command surface, and the pure `domain.rs` kernel documented as the C-ABI SPARK verification seam. CLAUDE.md's stale Python-proposing template replaced with an accurate agent guide that states the estate Rust/SPARK standard governs and Hypatia self-scans this repo (no Python, ever). docs/ and content/docs/ both updated; CHANGELOG keeps the Python era as labelled history. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root-cause sweep of the legacy `.hypatia-baseline.json` (99 -> 59). Every
real defect is fixed; every false positive is suppressed at the precise
site with a documented inline directive; only genuinely-still-present
entries remain baselined.
REAL FIXES (idiomatic Rust/SPARK: propagate with `?`, `.expect(<invariant>)`
for constant literals, explicit lock/rwlock poisoning handling — never a
bare `.unwrap()` or silent dangerous default). Each crate verified green
(build + clippy -D warnings + test):
- cipherbot: 74 `Regex::new(..).unwrap()` -> `.expect("static regex is
valid")` across 11 analyzers; completed the non-compiling `hashing.rs`
stub; policy.rs clippy.
- echidnabot: adapters {bitbucket,github,gitlab} clone-path + response
parsing now propagate via `?`/`ok_or_else` (were `.unwrap()` / silent
wrong defaults); stale test port assertion corrected at source.
- finishingbot: analyzer regexes already `?`/`.ok()?`/`.expect()`; fixed
pre-existing in-crate clippy blockers (default_constructed_unit_structs).
- glambot: 3 constant accessibility regexes -> `.expect(..)`.
- seambot: critical `count_seams(..).unwrap_or(0)` (masked a corrupt seam
register as "0 seams, clean") -> `?` + context; rwlock anti-pattern fixed.
- sustainabot-analysis: critical `load_snapshot` `.unwrap_or(0.0)`
(fabricated false critical health regressions) -> anyhow context
propagation; `compute_velocity` bounds `.expect(..)`.
- the-hotchocolabot: mock Mutex `.lock().unwrap()` -> poisoning-safe
`.unwrap_or_else(|e| e.into_inner())`; unwrap_without_check -> `.expect`;
resolved pre-existing crate breakage so it builds/tests green (safety-
relevant EuroBot hot-chocolate robot — robustness matters even in mocks).
- shared-context: 15 bench `.unwrap()` -> `.expect("bench setup: ..")`.
FALSE POSITIVES — suppressed with file-level `hypatia: allow` directives
naming the rule and the reason (fix > inline > ignore > baseline):
- 9 security_errors/secret_detected: cipherbot config.rs/infra.rs are
secret-DETECTION analyzers (their pattern literals are not credentials);
echidnabot {toml,example.toml} + docs and sustainabot DEPLOY.md /
GITHUB_APP_SETUP.md are documentation placeholders; scripts/
fix-{hardcoded-secrets,secret-to-env}.sh are remediation tools whose
illustration strings are the patterns they rewrite.
- 2 code_safety/shell_download_then_run: scripts/fix-{eval-to-safe,
heredoc-install}.sh are remediation tools that necessarily contain the
curl|bash/eval patterns they search for and annotate.
RESOLVED AT SOURCE:
- root_hygiene/banned docker-compose.yml: renamed `docker-compose.yml` ->
`compose.yml` (compose-spec canonical; podman-compose compatible) and
pointed both build refs at the existing `Containerfile`s (the referenced
`dashboard/Dockerfile` / `shared-context/fleet-cli/Dockerfile` did not
exist — a real broken-build bug); updated tests/e2e.sh. Aligns with the
estate Docker-policy change (Podman/Containerfile highly preferred;
hypatia PR hyperpolymath/hypatia#255).
REMAIN BASELINED (legitimately, with rationale):
- 35 cicd_rules/banned_language_file: gsbot Python — still present on
`main`; eliminated by the Rust/SPARK port PR #145.
Baseline reduction tracked there (item C), not here.
- 22 migration_rules/deprecated_api + 2 code_safety/obj_magic: all
`bots/sustainabot/bot-integration/**/*.res` — ReScript is hands-off for
bulk ops per estate policy; these are a deliberate, documented policy
baseline, not unaddressed negligence.
Refs hyperpolymath/hypatia#252
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- rsr-antipattern.yml: remove an orphaned dead second copy of the TypeScript-check program (lines after the first heredoc's PYEOF had no python3 opener, so bash executed 'BUILTIN_GLOBS = [' -> exit 127). The first step is complete and passes; the duplicate was a botched prior edit. Fails identically on main (pre-existing, not gsbot-port). - secret-scanner.yml: trufflehog action already passes --fail; the extra_args also passed --fail -> 'flag fail cannot be repeated'. Drop the duplicate, keep --only-verified. Pre-existing on main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…145/#146) Brings the full resolve-at-source sweep (8-crate idiomatic Rust fixes, 11 false-positive inline hypatia directives, docker-compose.yml -> compose.yml with real Containerfile refs) onto the gsbot Rust/SPARK port branch so #145 lands fully green in one piece. Baseline is regenerated post-merge for the post-port reality (Python eliminated). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…food-gate Closes the remaining #145 CI blockers (all pre-existing estate-wide, not introduced by the gsbot port — dogfood-gate fails identically on main): - .hypatia-baseline.json regenerated for the post-port reality: Python is eliminated (35 banned_language_file entries dropped — files no longer exist), every real defect is fixed and every false positive is suppressed via inline directives (merged from the resolve-at-source sweep), so the baseline is now exactly the 24 deliberately-retained ReScript bot-integration entries (22 migration_rules/deprecated_api + 2 code_safety/obj_magic; ReScript is hands-off per estate policy). This is item C, folded into #145. - A2ML: 6 `.a2ml` manifests lacked the validator's required identity field (agent-id|name|project). Added a meaningful identity key to each (CICD-PATTERNS, CLADE, anchors/ANCHOR, agent_instructions/{coverage, debt,methodology}); verified 0 identity errors against the upstream hyperpolymath/a2ml-validate-action logic. - K9: deploy-bot-fleet.k9.ncl used the flat pedigree shape with no name; added `pedigree.name = "deploy-bot-fleet"` (validator accepts pedigree.name). Verified 0 errors with the upstream hyperpolymath/k9-validate-action (strict:false, as the workflow runs). The gsbot Rust/SPARK port itself introduces no new critical/high Hypatia findings (0 `.unwrap()`, no unsafe/panic!/secret literals; `unwrap_or` uses are benign config defaults faithful to the Python original). Refs hyperpolymath/hypatia#252 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reproduced all three remaining #145 failures against the EXACT CI-pinned validators and fixed at source: - Hypatia gate (.github/workflows/hypatia-scan.yml): the matcher projected findings as a 5-tuple including `action` and did exact object equality, but its own contract comment says identity is the 4-tuple {severity,rule_module,type,file}. `action` is advisory, varies by run/strategy, and made every baseline entry fail to match (all 34 deliberately-baselined ReScript findings reported "new"). Dropped `action` from the projection and the regen hint so the documented 4-tuple is used; the 24-entry ReScript baseline now matches (Router.res ×3 etc. all collapse to one baseline entry). - A2ML (13 errors): the CI action is pinned to b2f28c39, an older, stricter validator than `main` (its is_manifest only exempts *AI-MANIFEST*; 6a2 typed manifests + contractiles are NOT exempt — why the earlier main-based simulation was wrong). Added a top-level `name` identity field to the 13 genuinely-failing files (.machine_readable/6a2/{AGENTIC,META,NEUROSYM,PLAYBOOK}, contractiles dust/trust/intend/must, robot-repo-automaton/6a2/*). - K9 (6 errors): the pinned validator (f985acb6) has a brace-tracking quirk — it doesn't count the `{` on the `pedigree =` line, so the first nested `}` ends pedigree scope prematurely and a `pedigree.metadata.name` is seen as outside pedigree. Added `name` as the FIRST pedigree field (before any nested block) to the 6 robot-repo-automaton k9 templates/examples. Verified locally with the byte-exact CI-pinned validator scripts (INPUT_STRICT=false, GITHUB_OUTPUT set): both now exit 0, Errors: 0. antipattern-check and trufflehog already pass from the prior commit. Refs hyperpolymath/hypatia#252 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🔍 Hypatia Security ScanFindings: 100 issues detected
View findings[
{
"reason": "Obj.magic bypassing type safety (2 occurrences, CWE-704)",
"type": "obj_magic",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/sustainabot/bot-integration/src/Analysis.res",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "Obj.magic bypassing type safety (2 occurrences, CWE-704)",
"type": "obj_magic",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/sustainabot/bot-integration/lib/ocaml/Analysis.res",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "expect() in hot path (1 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/gsbot/src/services.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "expect() in hot path (3 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/glambot/src/analyzers/accessibility.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "expect() in hot path (3 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/finishingbot/src/analyzers/claims.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "expect() in hot path (1 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/finishingbot/src/analyzers/license.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "expect() in hot path (1 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/accessibilitybot/src/analyzers/aria.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "expect() in hot path (5 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/accessibilitybot/src/analyzers/forms.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "expect() in hot path (4 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/accessibilitybot/src/analyzers/media.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "expect() in hot path (2 occurrences, CWE-754)",
"type": "expect_in_hot_path",
"file": "/home/runner/work/gitbot-fleet/gitbot-fleet/bots/accessibilitybot/src/analyzers/language.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
bots/gsbot(Garment Sustainability Bot) was the only Python in gitbot-fleet — 35.pyfiles, the source of the 35cicd_rules/banned_language_filecritical findings in the restored repo. Python is banned estate-wide with no exceptions; per the Rust/SPARK standard the sanctioned target is Rust/SPARK. This is a behaviour-preserving rewrite, not a rescaffold.Stack
gsbot is the fleet's first Discord bot. Mappings, chosen to match fleet conventions:
migrations/Rust/SPARK seam
src/domain.rsis the correctness-critical scoring kernel: pure, total functions plus a#[no_mangle] extern "C"FFI surface so a verified SPARK/Ada module can be linked in later via the standard Idris2-ABI / Zig-FFI pattern ("designed to admit SPARK modules even if it contains none yet"). All callers use safe wrappers, so substitution is transparent.Faithful behaviour
garment_materialsM2M; identical scoring (material mean, grade ladder, garment lifespan multiplier + 100 cap, environmental-impact averaging, user points/level ratchet, ranks, brand summary).on_command_errormessages, presence string.!loaddatafixtures: same 10 materials / 7 garments / 6 brands.scripts/*.py→ 3 bins (gsbot-load-fixtures,-export-data,-backup-db).lint/test/fmtrecipes preserved.Verification (local)
cargo build --all-targets— cleancargo clippy --all-targets -- -D warnings— cleancargo fmt --all -- --check— cleancargo test— 18/18 pass (domain 9, models 5, services 4)requirements.txt,setup.py,pytest.ini,alembic.ini, 35.py) →banned_language_fileclears for gsbot.Scope / safety
bots/gsbot/only. 38 tracked-file deletions — under the repo-integrity-guard's 50-file tripwire, so no[mass-delete-ok]marker needed; no critical paths touched.bots/gsbot/CLAUDE.mdis a stale generic template proposing Python; superseded by the estate Rust/SPARK standard (left as-is, out of scope).Refs hyperpolymath/hypatia#252
🤖 Generated with Claude Code