Skip to content

chore(sync): rattrapage main → develop (v0.35.1)#106

Merged
Destynova2 merged 79 commits intomainfrom
sync-main-v0.35.1-catchup
Apr 9, 2026
Merged

chore(sync): rattrapage main → develop (v0.35.1)#106
Destynova2 merged 79 commits intomainfrom
sync-main-v0.35.1-catchup

Conversation

@Destynova2
Copy link
Copy Markdown
Contributor

One-shot catch-up

Issue #82 items #27, #28. Main est actuellement en retard de ~15 commits sur develop, coincé a `Cargo.toml version = "0.35.0"` alors que le tag `v0.35.1` existe déjà. Le workflow `sync-main.yml` echouait depuis 2026-03-31 sur les 3 tag pushes (v0.34.0, v0.35.0, v0.35.1) à cause d'un `git push origin main` rejeté par la ruleset de branch protection.

Fix permanent : PR #105 (mergée juste avant celle-ci) a corrigé le workflow pour qu'il ouvre une PR au lieu de push direct. Les prochains tags seront synchronisés automatiquement.

Ce rattrapage one-shot promeut develop → main pour remettre les 2 branches en phase et débloquer les futures releases. Après merge :

Commits inclus

Tous ces commits ont déjà passé la CI sur develop individuellement.

Risque

  • Bas : develop est la source de vérité depuis toujours, main sert uniquement à la promotion release-plz
  • Pas de conflit prévu (main n'a aucun commit en propre depuis que la sync est cassée)
  • CI sur cette PR devrait passer puisqu'elle teste le même état que develop

Exception à CLAUDE.md

La règle "Never create a PR with develop as the head branch targeting main" existe pour éviter la suppression accidentelle de develop par l'auto-delete-head-branch. Ici j'utilise une branche dédiée `sync-main-v0.35.1-catchup` (pas develop directement) exactement pour respecter cette règle. La branche sera delete après merge, develop reste intouchable.

Test plan

  • CI verte sur cette PR (même contenu que develop, devrait passer sans souci)
  • Après merge : vérifier `git show main:Cargo.toml | grep version` → `0.35.1`
  • Vérifier que le prochain tag push déclenche le nouveau `sync-main.yml` et crée une PR sync propre

Destynova2 and others added 30 commits March 31, 2026 09:44
- Fix actionlint parameter: `flags` → `args` (rhysd/actionlint input name)
- Add URL exfiltration blocking on inbound requests in
  `sanitize_request_checked()` — was only checking responses, violating
  CONTRACTS.md INV-1 (security drift)
- Fix docs/QUICKSTART.md: replace `cargo install grob` (wrong crate) with
  brew/curl install methods
- Fix CLAUDE.md: container image size ~17MB → ~6MB (matches reality)
- Fix CONTRACTS.md + AGENTS.md: clarify SubagentTag returns RouteType::Default
  (no dedicated Subagent variant exists)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests now only wait for fmt + clippy + deny (fast gate) instead of all
11 quality checks. Slow checks (coverage, feature-check, semver, audit,
gitleaks, docs, machete) still run in parallel and are required by the
`required` gate job — they just no longer block test execution.

Expected improvement: ~3-5 min faster test feedback on PRs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove `audit-wire` path dependency from Cargo.toml — the crate lives
  outside the repo (`../shared/audit-wire`) so CI cannot resolve it.
  Will be reintroduced when published to a registry or vendored.
- Inline Windows feature flags instead of using a shell variable to
  satisfy shellcheck SC2086 (unquoted variable expansion).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SpendData gained a new pub field (by_provider_count) which
cargo-semver-checks flags as a major breaking change. Adding
#[non_exhaustive] allows future field additions without semver breaks.
Within the crate, struct literals still work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
grob is not published to crates.io, so semver-checks is informational
only. Internal trait changes (like provider_breakdown return type) are
intentional breaking changes that don't affect external consumers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… jobs

- Homebrew job now depends on `release` instead of `container`, ensuring
  GitHub Release assets exist before computing SHA256 checksums.
  Previously: homebrew ran before release → curl 404 on assets.
- Homebrew restricted to tag pushes only (no point on develop push).
- Path filter forces all outputs to `true` on tag pushes, preventing
  the entire build/test/release pipeline from being skipped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add .cargo/config.toml with musl target linker settings for cross.
  Dev builds use glibc (fast), release builds use cross for static
  musl+jemalloc binaries.
- Remove kraft.yaml (unikernel leftover from removed feature).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 10 tests for extract_trailing_literal_byte (dollar stripping, alpha
boundary walk, length threshold, alternation bail-out) and 5 tests for
DLP Display formatting and from_config secret+prefix counting.

Targets 13 MISSED mutants reported by cargo-mutants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document branching model (feature → develop → main), CI pipeline
stages, and release-plz flow so contributors and AI agents follow
the correct workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…shes

- Add src/ project structure overview for onboarding
- Update install URL to grob.sh shortlink
- Add development section (build, test, bench commands)
- Normalize em-dashes to ASCII double-dashes for terminal compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prompt contributors and AI agents to run `prek install` after cloning
so pre-commit hooks (fmt, clippy, gitleaks) catch issues before CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SpendData is an internal type (binary, not a crate). Replacing
#[non_exhaustive] with pub(crate) visibility hides it from the
public API entirely, which fixes the semver-checks breakage without
restricting internal construction.

Also narrows visibility of related spend functions and storage methods.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Grob is distributed as a standalone binary, not published on crates.io.
Semver compatibility checks on the public Rust API are meaningless and
were causing false failures (e.g. pub→pub(crate) visibility changes).

Remove from CI pipeline, prek pre-push hook, and CLAUDE.md references.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mutation test coverage, SpendData visibility fix, semver-checks
removal, prek setup docs, README improvements.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
release-plz skips semver checks for binaries automatically, but
making it explicit avoids confusion and documents the intent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Branch protection on main requires PRs and status checks, so
release-plz cannot push directly. Split into two jobs:
- develop push: release-pr (creates/updates PR to main)
- main push (after PR merge): release (creates git tag)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When `grob start` or `grob exec` detects missing OAuth tokens or API
keys, interactively prompt the user to configure them. Providers that
are already set up are silently skipped. Each missing provider can be
individually skipped to proceed with partial configuration.

Supports:
- OAuth flows: anthropic-max, openai-codex, gemini (print URL, paste code)
- API key entry: saved directly to config.toml
- Skip option: provider disabled until configured via `grob connect`
- TTY detection: non-interactive sessions skip prompts entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add critical rules to CLAUDE.md: never push to main, never PR from
develop to main, conventional commit scopes for release-plz.
Add Git Flow section to AGENTS.md with the same rules plus prek setup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PAT-based pushes to main don't trigger workflows (GitHub anti-loop
protection). Switch release-tag job from push trigger to
pull_request.closed with merged+release label condition.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Fix CircuitBreaker off-by-one: Open→HalfOpen transition now counts
   the first call, enforcing exactly half_open_max_calls. Add test.
2. Fix doc-code sync: README benchmark aligned with benchmarks.md
   (90µs/40x not 100us/50x), CLAUDE.md remove phantom shellcheck job,
   storage.md add missing by_provider_count field.
3. Pin cargo-machete to v0.9.1 (was @main — supply chain risk).
4. Update features.md version reference from v0.30.0 to v0.35.1.
5. Add 4 missing modules to CLAUDE.md module table.

Closes #82 items 1-5.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add E2E test suite for the full config lifecycle chain:
fresh install → setup wizard → doctor → start → proxy → reload → stop.

ADR-0008 documents the wizard architecture decision: unified config
engine with CLI/MCP/web surfaces, doctor checks, server/client modes.

Ref: #82 (items #29, #30, #31)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix run_test shell function (filter args, set -e arithmetic trap),
use GROB_HOME correctly, foreground start instead of detached mode,
add pass_through for mock provider routing.

All 10 tests pass with a Python mock on :8100.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
grob's OpenAI provider appends /chat/completions to base_url (without
/v1 prefix). VidaiMock expects the full /v1/chat/completions path.
Set base_url to include /v1 to match.

All 10 tests pass with vidaimock in podman container.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refactor setup wizard to collect-then-recap-then-write architecture:
- All choices collected in Choices struct before any disk write
- Recap screen with confirmation before writing config atomically
- Add --yes (accept defaults) and --dry-run (preview) flags
- Detect existing config and offer edit/replace/cancel
- Store API keys as $ENV_VAR references, never raw keys
- Simplify compliance screen from 7 to 5 options (GDPR+EU AI Act merged)
- Read provider list from preset TOML dynamically instead of hardcoded table

Additional fixes from wizard audit:
- Doctor returns meaningful exit codes (0=ok, 1=warnings, 2=errors)
- Web API config update creates backup before writing
- auto_flow.rs stops replacing $ENV_VAR with raw keys in config
- Preset apply supports --dry-run via preview_preset()

Add wizard Gherkin tests (6 scenarios, 21 steps):
- Unattended setup, dry-run, backup, env var refs, doctor, preset dry-run

setup.rs reduced from 800 to 620 lines (-22%).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove strategic positioning phrase from ADR-0006
- Remove broken link to deleted ADR-0007 in policies.md
- ROADMAP.md, ADR-0007, hit-quorum.md moved to private docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix run_test shell function (filter args, set -e arithmetic trap),
use GROB_HOME correctly, foreground start instead of detached mode,
add pass_through for mock provider routing.

All 10 tests pass with a Python mock on :8100.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Destynova2 and others added 25 commits April 6, 2026 16:18
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(security): ignore RUSTSEC-2025-0134 in cargo audit config
GitHub hosted runners need ~253s per mutant for a clean Rust build.
With 4 shards at 20min each, all shards were cancelled by timeout.
60min gives enough headroom for the hosted runner cold-build case.

For faster runs, use self-hosted Kube runners with cache PVC (salamandre).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): raise mutation testing timeout to 60 minutes
Runs clippy + tests on Rust beta and nightly every day at 03:00 UTC.
Beta must pass, nightly is allow-failure (continue-on-error).
Targets develop branch. Manually triggerable via workflow_dispatch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…_byte

Target mutation-vulnerable lines: >= 3 boundary, to_ascii_lowercase,
first-byte-of-run vs last, alternation bail, quantifier rejection,
dollar-anchor stripping, backslash handling, non-ASCII bytes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: add nightly/beta toolchain schedule workflow
…yte mutants

Add triple_dollar, pure_alpha_pattern, and single_char tests covering
dollar-stripping loop timeout, backward walk boundary, and end==0 mutations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exposes a `grob_configure` JSON-RPC method on POST /mcp that allows
MCP agents to read safe config subsets and update whitelisted runtime
parameters (router, budget, cache) with automatic hot-reload.

Security policy: DLP section is fully read-only; credential keys and
security core switches are on a deny-list and always rejected.

19 unit tests cover read/update/reject scenarios.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test(router): add 12 mutant-killer tests for extract_trailing_literal_byte
feat(mcp): add grob_configure self-tuning tool
…l_byte

Remplace les deux boucles `while end > 0 && ... { end -= 1; }` par des
appels a `rposition` + `map_or`. Les mutants cargo-mutants `-=` -> `/=`
transformaient les decrements d'index en `end /= 1` (no-op), ce qui
creait des boucles infinies non tuables par test (timeout systematique
sur le shard 1 de la matrice mutation testing).

Le comportement fonctionnel est strictement equivalent. Les tests
existants (trailing_literal_*) couvrent toutes les branches : ancres
'$' multiples, alpha run borderline, quantificateurs, unicode, etc.

Kills : L100 `end -= 1` et L112 `i -= 1` mutants.
…s et dfa.rs

Cible les mutants MISSED identifies par cargo-mutants sur les shards 2 (dlp/mod.rs)
et 4 (dlp/dfa.rs) de la matrice CI.

dlp/mod.rs (+6 tests, +refactor observabilite) :
- Expose `count_secret_rules` helper pour rendre l'addition `secrets + custom_prefixes`
  testable hors de `tracing::info!` (tue mutants `+` → `-`/`*` L229).
- Ajoute `scan_end_of_stream_reported` retournant un `EosScanReport` avec flags
  `*_scan_attempted` sur chaque branche conditionnelle, pour tuer les mutants
  `&& → ||` et `delete !` sur les gardes `!scanner.is_empty() && ...`,
  `!anonymizer.is_empty() && ...` et `!matches!(Clean)`. Les flags sont observables
  depuis les tests meme quand le garde secondaire (`redact`, `scan`) masque le
  resultat final.
- Tests couvrant les variantes `scan_input_enabled`/`scan_output_enabled` (stubs
  `-> bool`) via la trait `DlpPipeline`.

dlp/dfa.rs (+14 tests) :
- `might_contain_secret` seuil 512 bytes (`<= → >`) : borne 512/513 avec byte 'g'
  sans prefixe complet.
- `max_pattern_str_len` stub `-> 1` : compare a la longueur reelle et au cas vide.
- `scan` `matched_len: end - start` : token GitHub 40 bytes + AWS 20 bytes,
  decouple des bornes globales.
- `scan` tri des matches `> 1` : deux matches dans le desordre pour verifier
  la monotonie par position.
- `guess_family` `|| → &&` : un test par famille (github/llm/stripe/database)
  couvrant chaque alternative individuellement via helper `family_for_prefix`.
- Cas individuels aws/jwt/gitlab/pem + fallback generic.

Aucun changement de comportement prod : seul `scan_end_of_stream` recoit une
variante publique `_reported` et un helper d'arithmetique. L'API historique
reste identique (thin wrapper).
fix(router): corrige les timeouts mutants sur extract_trailing_literal_byte
test(dlp): ajoute 25 tests pour tuer les mutants survivants
…s paralleles

Le shard 3 (src/features/dlp/pii.rs) depassait systematiquement le budget
`timeout-minutes: 60` de cargo-mutants, ce qui faisait apparaitre l'ensemble
de la pipeline CI en `cancelled` depuis PR #95 (via le `needs:` du summary
`required`).

Split natif via `cargo mutants --shard K/N` : le meme fichier est teste par
deux jobs paralleles (3a = shard 0/2, 3b = shard 1/2), chacun prenant la
moitie des mutants. Pas de touche au code prod — seul le pilotage CI change.

Les shards 1, 2 et 4 restent inchanges (`mutants_shard: ""` → flag `--shard`
absent de la ligne de commande, comportement identique a avant).

Les artefacts `mutants-results-shard-*-${sha}` utilisent les nouveaux noms
"3a" et "3b" (pas de collision avec l'ancien shard "3").

Refs : T-CI-0c sprint grob-rebuild-2026-04.
…rror deja actif)

Le job `mutants` a deja `continue-on-error: true` pour que ses echecs ne
bloquent pas la pipeline. Le garder dans le `needs` du job `summary` etait
une double ceinture + bretelles : quand un shard etait `cancelled` (timeout
60min), la cancellation remontait dans le statut global du workflow et
faisait apparaitre l'ensemble de la pipeline en `cancelled` dans
`gh run list`, alors que fmt/clippy/tests/build etaient tous verts.

La sortie `mutants.out/` reste uploadee par le job lui-meme via son propre
step `actions/upload-artifact`. Les rapports restent consultables via le
lien d'artefact, et le job reste visible dans l'UI GitHub Actions — on ne
casse pas l'observabilite, on casse seulement la propagation de statut.

Nettoyage cosmetique : retire aussi 'mutants' de la liste `jobs` du script
de summary markdown (evite une ligne "n/a" quand `needs.mutants` n'existe
plus).

Le job `required` (merge queue gate, L932) ne contenait deja PAS `mutants`
dans son needs, donc le merge gate reste inchange.

Refs : T-CI-0d sprint grob-rebuild-2026-04.
Le workflow principal `ci.yml` ignore `docs/**` / `**.md` via `paths-ignore`.
Sur une PR docs-only (ex: docs/adr-backfill, PR #101), aucun des jobs
required declares dans le ruleset develop ("Rustfmt", "Clippy (ubuntu-latest)",
"Test (ubuntu-latest)") n'est declenche. Consequence : `statusCheckRollup: []`
et GitHub bloque le merge en deadlock.

Solution : un second workflow qui declare les memes `name: CI` et memes job
display names que `ci.yml`, avec des steps triviaux (`echo`). Il se declenche
uniquement sur les chemins que le workflow principal ignore, donc les deux
sont mutuellement exclusifs pour les commits docs-purs.

Les trois jobs du shim reprennent les noms exacts attendus par le ruleset :
- `Rustfmt` (miroir de `fmt:` / L128 de ci.yml)
- `Clippy (ubuntu-latest)` (miroir de la cellule matrice de `clippy:` / L144)
- `Test (ubuntu-latest)` (miroir du gate `test-ubuntu-gate:` / L377)

Pour les commits mixtes (docs + code), les deux workflows tournent en
parallele. GitHub resout les status checks par nom : le workflow principal
(plus lent mais realiste) ecrase le shim (instantane), donc le statut final
reflete toujours la realite du code.

Cout : 3 jobs ubuntu-latest triviaux (~15s chacun) par push/PR docs-only.

Refs : T-CI-0e sprint grob-rebuild-2026-04.
fix(ci): debloque pipeline mutants et ajoute shim docs
#105)

Le workflow `sync-main.yml` tentait un `git push origin main` apres
merge develop. La ruleset de branch protection sur main exige que
tout changement passe par une PR, donc le push etait rejete avec
`GH013: Repository rule violations`. Consequence: main reste stuck
aux versions precedentes et les tags pointent sur des Cargo.toml
desaccordes (v0.35.1 vs v0.35.0).

Nouveau flow:
1. Crée une branche courte `sync-main-<tag>` depuis develop
2. La push sur origin (force-with-lease pour idempotence)
3. Ouvre une PR vers main avec label `sync-main` (idempotent: reutilise
   la PR existante si on retry)
4. Active l'auto-merge squash pour que la PR se merge des que CI passe

Corrige issue #82 items #27 #28 #37.

Co-authored-by: commis-ci-fix <commis-ci-fix@grob.local>
Main avait diverge de develop depuis que sync-main.yml etait casse
(2026-03-31). Ce merge absorbe l'historique de main (release-plz bumps,
CI fixes, tests, docs) mais prefere develop sur tous les conflits de
contenu, puisque develop est la source de verite.

Commits de main unifies:
- release-plz bumps v0.34.0, 0.35.0
- fix(ci): split release-plz, semver-checks, audit-wire path
- test(router,dlp): mutants survivants (deja couvert par T-CI-0)
- docs(claude,readme): prek setup, git flow, install URL

Contenu final = etat actuel de develop.
@Destynova2 Destynova2 enabled auto-merge (squash) April 9, 2026 21:40
Le merge `-X ours` de `origin/main` dans la branche catchup a concatene
les blocs non-conflictuels au lieu de garder une seule version.

- release-plz.yml : 2e bloc `on:` (version simple de main) → supprime,
  on garde celui de develop qui a pull_request closed pour release-tag
- CLAUDE.md : 2e sections "Local Setup" et "Git Flow & CI/CD" (version
  courte de main sans "Critical Rules") → supprimees, on garde celles
  de develop qui ont les "Critical Rules" plus complet

actionlint sur release-plz.yml avait flagge:
  key "on" is duplicated in "workflow" section. previously defined at line:7,col:1
@Destynova2 Destynova2 merged commit 0c7441b into main Apr 9, 2026
35 checks passed
@Destynova2 Destynova2 deleted the sync-main-v0.35.1-catchup branch April 9, 2026 21:59
Comment thread src/auth/auto_flow.rs
oauth_provider_id,
..
} => {
eprintln!(
Comment thread src/auth/auto_flow.rs
let config = match oauth_config_for_type(oauth_type) {
Some(c) => c,
None => {
eprintln!(" ❌ Unknown OAuth type: {}", oauth_type);
Comment thread src/commands/setup.rs
println!(" Providers:");
for a in &c.auth {
if a.use_oauth {
println!(" {:<14} OAuth ({})", a.provider, a.oauth_id);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants