chore: split cloud/ and marketing/ to private gradata-cloud#76
Conversation
- Moves cloud/dashboard, cloud/backend, and marketing/ to new private repo - Full git history preserved via git-filter-repo - gradata (public) now contains SDK + plugin + npm wrapper + docs + examples only - Proprietary dashboard/backend/marketing code closed-sourced per architectural split - Removes dashboard-source-maps.yml and loadtest-nightly.yml (both targeted cloud/ paths) Signed-off-by: Oliver Le <oliver@gradata.ai>
|
Too many files changed for review. ( |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (244)
💤 Files with no reviewable changes (188)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
📝 Walkthrough• Architectural split: Removes • Backend removal: Deletes entire FastAPI backend including all • Dashboard removal: Deletes Next.js React dashboard application and all UI components across 50+ page and component files • Database schema removal: Deletes all Supabase migrations (001-007), including tables for brains, corrections, lessons, meta-rules, webhooks, telemetry, and soft-delete infrastructure • Infrastructure removal: Eliminates Docker configuration, Railway deployment settings, k6 load test scripts, Cloudflare Workers proxy, and Sentry integrations • Workflow deletion: Removes • Breaking changes: All cloud-hosted services (API, dashboard, Stripe billing, authentication, GDPR endpoints) are no longer in the public repository • SDK unchanged: Documentation references in WalkthroughThis pull request removes the entire Gradata Cloud infrastructure, including the FastAPI backend API on Railway, the Next.js dashboard frontend on Cloudflare Pages, all database migrations, GitHub Actions workflows, documentation, and supporting infrastructure files totaling 170+ deletions. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
The return type was list[tuple[object, float]] which made pyright reject attribute access on the unpacked rule (r.state, r.confidence, etc). Switch to the actual Lesson type (or Any if Lesson import is awkward). Unblocks PR #76 (cloud-split) which inherits this CI failure. Signed-off-by: Oliver Le <oliver@gradata.ai>
- Move Lesson import into TYPE_CHECKING block (ruff TC001) - Cast scope-applies expression to bool to satisfy pyright reportReturnType - rule_context fix is pre-existing on main, blocking the same CI as PR #76 Signed-off-by: Oliver Le <oliver@gradata.ai>
* fix(types): annotate rank_rules_for_draft to satisfy pyright The return type was list[tuple[object, float]] which made pyright reject attribute access on the unpacked rule (r.state, r.confidence, etc). Switch to the actual Lesson type (or Any if Lesson import is awkward). Unblocks PR #76 (cloud-split) which inherits this CI failure. Signed-off-by: Oliver Le <oliver@gradata.ai> * fix(types): TYPE_CHECKING for Lesson + bool-narrow rule_context return - Move Lesson import into TYPE_CHECKING block (ruff TC001) - Cast scope-applies expression to bool to satisfy pyright reportReturnType - rule_context fix is pre-existing on main, blocking the same CI as PR #76 Signed-off-by: Oliver Le <oliver@gradata.ai> * fix(types): group TYPE_CHECKING with stdlib imports (ruff I001) Signed-off-by: Oliver Le <oliver@gradata.ai> * refactor(rule_context): drop redundant bool() wrapper per CR startswith() already returns bool; the 'and applies' short-circuit is also redundant since startswith() on empty string is False for any non-empty pattern. Signed-off-by: Oliver Le <oliver@gradata.ai> --------- Signed-off-by: Oliver Le <oliver@gradata.ai>
…ebase onto main Rewrite TestSelfHealingE2E::test_inline_auto_heal_emits_rule_patched and TestCorrectAutoHealIntegration::test_auto_heal_emits_patch_when_retroactive_test_passes to exercise ONLY the inline `brain.correct(auto_heal=True)` path. Remove the manual `review_rule_failures()` + `brain.patch_rule()` fallback so a regression in the inline orchestration fails the test instead of being masked by the fallback emitting RULE_PATCHED on its own. Also address three smaller CR items: - `_core.py`: forward `auto_heal` through the cloud branch by falling back to the local pipeline when the flag is set (cloud client does not yet carry the flag), so `auto_heal=True` is no longer silently dropped in cloud-connected brains. - `_core.py`: route the auto-heal notice through `_log.warning` instead of `print(..., file=sys.stderr)` to keep the SDK logging pipeline consistent. - `brain.py`: invalidate `_rule_cache` after `Brain.auto_heal()` applies patches, so later `apply_brain_rules()` calls see the patched prompt. Rebased onto origin/main (includes #76 cloud split, #80 distribution, #81 rule-to-hook auto-promotion). Rebase was conflict-free -- zero file overlap between this branch and the three landed PRs. Co-Authored-By: Gradata <noreply@gradata.ai>
…() (Phase 1) (#77) * feat(self-healing): close the auto-heal loop brain.auto_heal() reads recent RULE_FAILURE events, runs review_rule_failures, gates each candidate through retroactive_test, and applies the survivors via brain.patch_rule. Batches are deduped by (category, original_description) and hard-capped at max_patches (default 5) so a single session can't rewrite a rule multiple times. Before this commit, PR #21 emitted RULE_FAILURE but nothing consumed it. The full flow required the caller to manually call review_rule_failures + brain.patch_rule as the E2E test does. Adds auto_heal_failures(brain, ...) orchestrator in self_healing.py and Brain.auto_heal public method that delegates to it. 6 new tests covering empty input, passing candidate, retro-test failure, in-batch dedup, max_patches cap, and event-log read when no events are passed. * feat(self-healing): wire auto_heal into brain.correct() by default When brain.correct() detects a RULE_FAILURE it now invokes auto_heal_failures inline, capped at one patch per call so a single correction can rewrite at most the rule it just failed. Skipped in dry_run, approval_required, and renter modes; opt-out via correct(auto_heal=False). Adds auto_heal kwarg to brain.correct + brain_correct in _core.py and surfaces the heal summary on event["auto_healed"] when a patch lands. 3 new tests covering the default-on path, the opt-out path, and the dry_run skip. Closes the diagnose-then-do-nothing gap that PR #21 left open. * fix(self-healing): default auto_heal=False per council; add PatchReceipt for visibility Polyclaude council verdict (4/4 FALSE) on Phase 1: default auto_heal=True is too hot. Ship False default plus a visible PatchReceipt so any auto-heal that does fire is loud, not silent. Flip to True deferred until (a) a pending_patches review queue and (b) ablation showing rule-quality lift on a held-out broken-rule corpus. - brain.correct() and _core.brain_correct() default auto_heal to False - auto_heal_failures() returns PatchReceipt dicts: rule_id, old/new confidence, patch_diff, revert_command (legacy fields kept for BC) - _core emits one stderr line per successful auto-heal patch so silent rule edits cannot sneak through - tests: opt-in explicit auto_heal=True on existing integration tests, plus new test_default_off_no_patch and test_patch_receipt_shape Co-Authored-By: Gradata <noreply@gradata.ai> * fix(self-healing): address CodeRabbit review on #77 (docstring + type ann + test fixture) - Document auto_heal parameter on Brain.correct (defaults to False post-council) - Add forward-ref Brain type annotation on auto_heal_failures via TYPE_CHECKING - Hoist brain_with_rule to module-scope fixture and remove 5 duplicated class-level copies - Split weak test_auto_heal_triggers_on_rule_failure into two deterministic tests: one asserts rule_failure_detected only, the second drives auto_heal_failures with known-good delta words and asserts patched==1 plus auto_heal: reason prefix Co-Authored-By: Gradata <noreply@gradata.ai> * fix(self-healing): address CodeRabbit on inline auto-heal coverage; rebase onto main Rewrite TestSelfHealingE2E::test_inline_auto_heal_emits_rule_patched and TestCorrectAutoHealIntegration::test_auto_heal_emits_patch_when_retroactive_test_passes to exercise ONLY the inline `brain.correct(auto_heal=True)` path. Remove the manual `review_rule_failures()` + `brain.patch_rule()` fallback so a regression in the inline orchestration fails the test instead of being masked by the fallback emitting RULE_PATCHED on its own. Also address three smaller CR items: - `_core.py`: forward `auto_heal` through the cloud branch by falling back to the local pipeline when the flag is set (cloud client does not yet carry the flag), so `auto_heal=True` is no longer silently dropped in cloud-connected brains. - `_core.py`: route the auto-heal notice through `_log.warning` instead of `print(..., file=sys.stderr)` to keep the SDK logging pipeline consistent. - `brain.py`: invalidate `_rule_cache` after `Brain.auto_heal()` applies patches, so later `apply_brain_rules()` calls see the patched prompt. Rebased onto origin/main (includes #76 cloud split, #80 distribution, #81 rule-to-hook auto-promotion). Rebase was conflict-free -- zero file overlap between this branch and the three landed PRs. Co-Authored-By: Gradata <noreply@gradata.ai> * fix(self-healing): use contextlib.suppress for cache invalidation (Ruff SIM105) CodeRabbit's 3rd review on PR #77 + CI Ruff job both flagged the try/except/pass block at brain.py:548-552 as SIM105 violation. Replaced with contextlib.suppress(Exception) (contextlib already imported at line 51). Behavior unchanged. Co-Authored-By: Gradata <noreply@gradata.ai> --------- Co-authored-by: Gradata <noreply@gradata.ai>
Both dirs were removed from the repo when cloud/ + marketing/ moved to private Gradata/gradata-cloud (#76), but the files remain on local checkouts. Gitignoring stops the churn in git status. Co-Authored-By: Gradata <noreply@gradata.ai>
Both dirs were removed from the repo when cloud/ + marketing/ moved to private Gradata/gradata-cloud (#76), but the files remain on local checkouts. Gitignoring stops the churn in git status. Co-authored-by: Gradata <noreply@gradata.ai>
(c) Wire dormant emitter ------------------------ SessionHistory in integrations/session_history.py subscribes to `rules.injected` but nothing in the codebase ever emits it — grep of the whole tree shows only the subscriber. That leaves its per-session rule effectiveness tracking (compute_effectiveness / on_session_ended) silently dead. brain.apply_brain_rules() now fires the event on the in-memory bus after format_rules_for_prompt(applied). Cache hits skip the emit intentionally: SessionHistory dedups via a set, the cache is per scope, and every fresh scope hits the compute path. The other two events SessionHistory subscribes to (correction.created, session.ended) already have emitters — checked at _core.py:138, 574, 854. So this is the one missing wire. Regression test: test_apply_brain_rules_emits_rules_injected — seeds a graduated TONE rule through a real correct() loop, subscribes a SessionHistory to the brain's bus, calls apply_brain_rules, asserts the injected set is populated. (b) Gitignore on-disk orphans ----------------------------- Three untracked leftovers from the S105 repo splits keep showing up in `git status` and sometimes get accidentally re-added: - /cloud/ moved to private Gradata/gradata-cloud (#76) - /sdk/ superseded by the flattened layout (#65) - /railway.toml now lives in gradata-cloud/cloud/railway.toml Also added apollo-leads-*.csv since sales exports have leaked into the repo root before and belong in brain/leads/, not the SDK tree. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(c) Wire dormant emitter ------------------------ SessionHistory in integrations/session_history.py subscribes to `rules.injected` but nothing in the codebase ever emits it — grep of the whole tree shows only the subscriber. That leaves its per-session rule effectiveness tracking (compute_effectiveness / on_session_ended) silently dead. brain.apply_brain_rules() now fires the event on the in-memory bus after format_rules_for_prompt(applied). Cache hits skip the emit intentionally: SessionHistory dedups via a set, the cache is per scope, and every fresh scope hits the compute path. The other two events SessionHistory subscribes to (correction.created, session.ended) already have emitters — checked at _core.py:138, 574, 854. So this is the one missing wire. Regression test: test_apply_brain_rules_emits_rules_injected — seeds a graduated TONE rule through a real correct() loop, subscribes a SessionHistory to the brain's bus, calls apply_brain_rules, asserts the injected set is populated. (b) Gitignore on-disk orphans ----------------------------- Three untracked leftovers from the S105 repo splits keep showing up in `git status` and sometimes get accidentally re-added: - /cloud/ moved to private Gradata/gradata-cloud (#76) - /sdk/ superseded by the flattened layout (#65) - /railway.toml now lives in gradata-cloud/cloud/railway.toml Also added apollo-leads-*.csv since sales exports have leaked into the repo root before and belong in brain/leads/, not the SDK tree. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Architectural split per the 2-repo plan:
cloud/andmarketing/now live at Gradata/gradata-cloud (private)git-filter-repoAlso removed
.github/workflows/dashboard-source-maps.yml(targetedcloud/dashboard/**).github/workflows/loadtest-nightly.yml(ran k6 fromcloud/loadtest/)Both workflows are being migrated to the private repo separately.
Not touched
pyproject.tomlcloud = []extra — this is an SDK Python extra for the cloud client, unrelated to thecloud/directory.gitignoredocs/cloud/— unrelated generated docs pathsdk/mkdocs.ymlcloud docs nav — references SDK-side cloud docs, not the removed directoryTest plan
Gradata/gradata-cloudprivate repo contains preserved historycloud/ormarketing/paths break SDK build