Skip to content

chore(git): rename Dev_new_gui to main and main to release across the repo (#16479) - #16487

Merged
mrveiss merged 1 commit into
mainfrom
issue-16479-branch-name-swap
Sep 12, 2026
Merged

mrveiss merged 1 commit into
mainfrom
issue-16479-branch-name-swap

Conversation

@mrveiss

@mrveiss mrveiss commented Sep 12, 2026 •

Copy link
Copy Markdown
Owner

Refs #16479
Refs #16461

Single-issue rationale: this delivers #16479, the in-repo half of the branch rename (#16461). The GitHub-side renames already ran, and production moving to main plus the mirror's removal are later steps of the same issue. So this PR references #16461 and doesn't close it.

Thinking Path

The owner chose standard branch naming. The working branch Dev_new_gui is now main, the default branch, and the old main is now release. The GitHub-side renames are done:

  • main → release
  • Dev_new_gui → main; GitHub retargeted every open PR
  • the review ruleset now points at main
  • a temporary Dev_new_gui mirror keeps the live updater fetching until production tracks main

This PR makes the repository agree with the new names. The two names swap: old Dev_new_gui references become main, and old main references become release, but only where they meant the release branch. main as a function, __main__, a Redis database name or "main process" is untouched.

What Changed

  • Dev_new_gui → main (505 lines across 204 files): workflow branch filters and ref checks, dependabot.yml, pre-commit and .claude hooks, tools/git-hooks, scripts, the updater defaults (git_tracker.py SLM_REPO_BRANCH, playbook_executor.py AUTOBOT_GIT_BRANCH, the Ansible deploy_ref), CLAUDE.md and the current process docs. Dated historical records are left as they are.
  • main → release where it meant the release branch (a 172-line list, each line reviewed). This covers release.yml, the weekly sync, whose direction is now main → release and whose workflow is renamed sync-main-to-release.yml, the release-sync scripts and tests, and the protected-branch lists.
  • Kept for the mirror: Dev_new_gui stays in every branch-automation exclusion list (cleanup, health and stale-branch reports, the parked-branch merger's never-target list, worktree cleanup) and in the push-protection hook, so nothing deletes, merges into or pushes to the mirror. Each entry is commented for removal under infra(git): rename Dev_new_gui to main and main to release, without breaking the live updater #16461.
  • New mirror-main-to-legacy-dev-branch.yml: fast-forwards Dev_new_gui to every push on main, with no force. It's temporary, and removed under infra(git): rename Dev_new_gui to main and main to release, without breaking the live updater #16461 once production tracks main.

Verification

  • Every main → release change is listed and was reviewed line by line before pushing.
  • git grep Dev_new_gui outside dated history finds only the mirror workflow and the "kept for the mirror" exclusions: the mirror workflow, the marked exclusions, one #16461 note in release_sync_main.py, and dated historical documents. Five files still blocked by pre-existing debt in the same file, and five rules whose reasons the new model contradicts, are tracked in infra(git): rename leftovers: five files blocked by pre-existing debt, and rules the new branch model contradicts #16482.
  • YAML parses, shell passes bash -n, and Python compiles. CI on this PR is the first run under the new branch names.

Model Used

Claude Opus 5 (coordinator, review of every release-context change) with a Claude Sonnet 5 subagent for the edits.

Why this PR only references #16479: its first criterion says no workflow, script, hook, config or code default names Dev_new_gui. Five leftover files still do, including install.sh's DEFAULT_BRANCH and slm-migration-gate.yml, and they're deferred to #16482. #16479 is finished when #16482 lands.

… repo (#16461)

Simultaneous branch-name swap: every Dev_new_gui reference in executable and
config files becomes main, and every main reference that names the release
branch becomes release, never both collapsing into one name. Covers 54
workflows plus dependabot.yml, pre-commit config/hooks, git-hooks, scripts,
Ansible deploy_ref defaults, the SLM/backend code defaults
(SLM_REPO_BRANCH/AUTOBOT_GIT_BRANCH), frontend/backend literals and their
tests, and current-process docs (CLAUDE.md, docs/developer/*, .claude/skills).

Renames .github/workflows/sync-main-to-dev.yml to sync-main-to-release.yml
and reverses its direction (main -> release), updating
pipeline-scripts/release_sync_main.py, release_sync_pull.py and their tests
to match. Adds the temporary .github/workflows/mirror-main-to-legacy-dev-branch.yml
so the live updater keeps fetching Dev_new_gui as a fast-forwarded mirror of
main until production is confirmed tracking main (#16461 also tracks its
removal). Every branch-deletion/merge/retarget workflow and script keeps
Dev_new_gui in its exclusion or never-target list for the same reason.

pages.yml's ruby/setup-ruby@v1 is SHA-pinned in passing (#7091's gate fired on
it once the file was touched); repo_tests/ci_dispatch_watchdog_test.py's
file-size ceiling is lowered to match black's reformat (#5060 ratchet only
turns down).

Five files are left untouched: editing any of them trips a pre-existing,
unrelated lint/hardcoded-value/async-IO/mypy gate on debt already in the file
(a gate that cannot be baselined for a file the same change touches, per its
own no-bypass rule) --
  - docs/_config.yml (hardcoded GitHub URL pattern)
  - install.sh (chown/path/URL literals)
  - .claude/skills/claims-audit/generate_report.py (flake8/print())
  - .github/workflows/slm-migration-gate.yml (hardcoded :5432)
  - autobot-backend/services/knowledge/code_indexer_test.py (26 pre-existing
    blocking-I/O-in-async findings)
  - autobot_shared/user_management/models/core_test.py (pre-existing mypy
    strict errors on importlib.util.module_from_spec's Optional return)
Each needs its own debt fix before its branch-name reference(s) can be renamed.

Dated historical records (docs/archives, changelog/, docs/research,
docs/superpowers/plans+specs, docs/audit, docs/adr, docs/prd, docs/planning,
docs/analysis, docs/design, docs/discovery, and auto-generated
docs/verification*.json/md, docs/system-state.md) are left untouched.
@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 07bf4b79-339e-4be5-a8ad-613dbfd84902


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No new hardcoded values of either class — ssot and other both block.

Known backlog in pipeline-scripts/hardcoded_values_baseline.txt is suppressed and tracked in #14371.

@github-actions

Copy link
Copy Markdown
Contributor

Notice: 29 open PRs — past the runaway threshold (25)

There is no PR queue limit, and this is not a request to defer this PR. Work proceeds one issue at a time without a cap on open PRs; review capacity is the constraint.

This notice only means the count is high enough to be worth a glance for a runaway — something opening PRs in a loop, or a merge pipeline that has stalled so nothing is draining.

Currently open:

If the queue is draining normally, ignore this. Otherwise:

  1. Check whether CI is dispatching at all — see the ci-dispatch-watchdog status on these PRs
  2. Merge the ones whose CI has finished and review has passed: gh pr merge <number> --squash --delete-branch
  3. Look for a loop opening near-identical PRs

Warn-only runaway detector — .github/workflows/pr-queue-gate.yml. It never blocks a merge.

@mrveiss
mrveiss merged commit 1eb2479 into main Sep 12, 2026
102 of 115 checks passed
@mrveiss
mrveiss deleted the issue-16479-branch-name-swap branch September 12, 2026 21:15
mrveiss added a commit that referenced this pull request Sep 12, 2026
…ep, after the rename (#16198)

The sweep's workflow, scope module, offender baseline and test were written before #16487 renamed Dev_new_gui to main, so its push and pull_request triggers still named a branch that is now only a mirror.
mrveiss added a commit that referenced this pull request Sep 13, 2026
…ep, after the rename (#16198)

The sweep's workflow, scope module, offender baseline and test were written before #16487 renamed Dev_new_gui to main, so its push and pull_request triggers still named a branch that is now only a mirror.
mrveiss added a commit that referenced this pull request Sep 13, 2026
…ain (#16464) (#16467)

* fix(migrations): port 6 orphaned tables into the canonical Alembic chain (#16464)

session_collaborations, terminal_activities, file_activities,
browser_activities, desktop_activities and secret_usage are all declared in
real ORM models (models/session_collaboration.py, models/activities.py) but
were never reachable via `alembic upgrade head` -- they only existed in
autobot-backend/database/migrations/, which migrations/alembic.ini does not
point at (script_location = migrations, version_locations =
migrations/versions). migrations/schema_bootstrap.py confirms there is no
silent create_all() fallback against a real database either. Same class of
bug as #10750 A2, which found and fixed 8 LLC tables in exactly this state.

Highest-impact finding: every one of the five activity/secret_usage tables
carries ForeignKey("users.id", ondelete="CASCADE"), and users.org_id is
itself ForeignKey("organizations.id", ondelete="CASCADE"). A missing CASCADE
target doesn't just make the table unreachable -- it makes hard-deleting a
user, or an organization (which cascades into its users), fail outright
against any properly-migrated database. Not hypothetical: confirmed on a
live install (37's probe entities). Two new tests
(tests/migrations/test_cascade_delete_orphaned_tables_16464.py) exercise
exactly that at the database level and pin it fixed.

session_collaborations is what api/collaboration.py's entire REST API
depends on (#16429/#16443/#16455/#16462) -- every one of those routes 500'd
(UndefinedTableError) against a real database until this migration.

Also added:
- Both new concepts (session_collaboration, activity_audit_trail) declared
  in autobot_shared/store_authority.py, with a SYSTEM_OF_RECORD =
  system_of_record(...) call at each model file's module level.
- repo_tests/orphaned_database_migrations_test.py: a general guard that
  fails the moment a NEW table lands in database/migrations/ without a
  matching CREATE TABLE in migrations/versions/, so this class of defect
  can't recur silently and get found by hand again.

Deliberately excluded: database/migrations/001_create_conversation_files.py
looks like the same bug at a glance (same orphaned directory) but manages
its own dedicated SQLite file via a self-contained, live-invoked migration
runner -- checked and confirmed unrelated.

Follow-up filed: #16466 (3 of the 5 activity-tracking backend modules --
terminal/file/browser -- have zero real callers; wire or retire).

Migration is fully additive (CREATE TABLE / CREATE INDEX only, nothing
dropped) and idempotent (has_table()-guarded). Deliberately fully inlined
per-table rather than a shared helper, matching #10750 A2's own style --
repo_tests/orphaned_database_migrations_test.py reads table names via AST
from literal op.create_table("name", ...) calls, and a name passed through
a helper's parameter is invisible to that scan.

* docs(changelog): add fragment for #16464

* security(chat): scan/redact PII and flag injection risk on every raw chat message (#16529, #16530)

* security(chat): scan/redact PII and flag injection risk on every raw chat message (#16529, #16530)

Internal audit of the LLM request pipeline found api/chat.py forwarded the
raw user message to the LLM (and to persistent storage) without ever
calling the existing PII pipeline (a2a/pii_pipeline.py) or the existing
prompt-injection detector (security/prompt_injection_detector.py) -- both
were wired to narrower features but never to the literal chat message on
any turn.

Adds security/chat_message_safety.py as the one choke point every raw-
message entry point in chat.py now calls first: /chat, /chat/stream (both
branches), the frontend's primary /chats/{id}/message path, /chat/direct,
and /ai-stack + /stream-ai-stack. PII reuses the existing BLOCK/REDACT/HASH
policy unchanged via scrub_outbound(); SSN/API-key/card/JWT-shaped content
is rejected before the LLM call, lower-severity types are redacted in
place. Injection detection flags and logs HIGH/CRITICAL hits rather than
blocking outright -- measured directly against a benign-message sample
while wiring this in, the shared detector's pattern set false-positives on
ordinary chat phrasing ("you are a great assistant"), so a flat block
would reject legitimate turns. The existing
AUTOBOT_INJECTION_HARDBLOCK_ENABLED opt-in still rejects a message when an
operator has turned on stricter enforcement.

chat.py is a grandfathered file frozen at its current line count (#14236);
the five call sites land as in-place line edits (tuple-assignment /
inline-call) rather than new lines, so the file's size does not change.

* fix(security): match the injection-detector singleton's locked construction args (#16529, #16530)

get_prompt_injection_detector() is a lazy_singleton(PromptInjectionDetector):
whichever caller constructs it first fixes its args for the process, and
every later caller passing different args gets an error instead of the
detector. Every existing call site (prompt_manager.py, screen_analysis_
prompt.py, chat_knowledge_prompt.py, intent_analyzer.py, ...) already uses
strict_mode=True; the new chat safety module called it bare, so whichever
of the two constructed first could poison the other depending on import/
call order. Caught by running the new tests alongside tests/test_injection_
detection.py, where TestPromptManagerInjectionDetection started failing
with a "lazy_singleton: called with different args" log line.

* fix(chat): surface a real 400 for a blocked streaming message, not a generic SSE error (#16529, #16530)

Code-review follow-up on the /chat/stream path: scan_chat_message() ran
inside _generate_llm_stream's try block, so a PIIBlocked/hard-block
HTTPException(400) was caught by that function's own broad
except Exception and downgraded to a generic {"type":"error"} SSE event at
HTTP 200 -- the LLM was still never called (already covered by a test),
but the client could not distinguish "blocked by policy" from "the LLM
failed", unlike the other four call sites, which all return a real 400.

Moves the scan into stream_message() itself, before stream_chat_response()
ever constructs a StreamingResponse -- a StreamingResponse commits to its
status code the moment it is returned, before its body generator is
entered, so scanning there is the only way to get a genuine pre-stream 400.
_generate_llm_stream no longer scans; by the time it runs, message.content
is already clean.

Also: standardised two more #16529-only comment tags to #16529/#16530 for
consistency (a third stays #16529-only -- the full tag would exceed this
frozen file's 120-char line limit), and added an injection-flagged-but-not-
blocked behavioral test at each of the five call sites -- the existing
tests only covered the PII-block path per site, not that the #16530
false-positive guard (flag-and-log, not block) actually holds through the
real wiring and not just the primitive.

* test(migrations): supply every required column in the cascade tests' activity inserts (#16464)

migration-matrix was red on #16467: both cascade tests inserted activity rows
with only (id, user_id), and the migrated schema declares NOT NULL columns on
all four activity tables (terminal_activities.command, file_activities
operation/path, browser_activities url/action, desktop_activities.action) --
NotNullViolationError. The migration was right; the fixture was incomplete.
_required_columns reads every NOT NULL column without a default from the
migrated schema and supplies a placeholder per type, failing by name on a type
it has none for, so a future required column is caught rather than skipped.
Migration and models unchanged.

* chore(git): rename Dev_new_gui to main and main to release across the repo (#16461) (#16487)

Simultaneous branch-name swap: every Dev_new_gui reference in executable and
config files becomes main, and every main reference that names the release
branch becomes release, never both collapsing into one name. Covers 54
workflows plus dependabot.yml, pre-commit config/hooks, git-hooks, scripts,
Ansible deploy_ref defaults, the SLM/backend code defaults
(SLM_REPO_BRANCH/AUTOBOT_GIT_BRANCH), frontend/backend literals and their
tests, and current-process docs (CLAUDE.md, docs/developer/*, .claude/skills).

Renames .github/workflows/sync-main-to-dev.yml to sync-main-to-release.yml
and reverses its direction (main -> release), updating
pipeline-scripts/release_sync_main.py, release_sync_pull.py and their tests
to match. Adds the temporary .github/workflows/mirror-main-to-legacy-dev-branch.yml
so the live updater keeps fetching Dev_new_gui as a fast-forwarded mirror of
main until production is confirmed tracking main (#16461 also tracks its
removal). Every branch-deletion/merge/retarget workflow and script keeps
Dev_new_gui in its exclusion or never-target list for the same reason.

pages.yml's ruby/setup-ruby@v1 is SHA-pinned in passing (#7091's gate fired on
it once the file was touched); repo_tests/ci_dispatch_watchdog_test.py's
file-size ceiling is lowered to match black's reformat (#5060 ratchet only
turns down).

Five files are left untouched: editing any of them trips a pre-existing,
unrelated lint/hardcoded-value/async-IO/mypy gate on debt already in the file
(a gate that cannot be baselined for a file the same change touches, per its
own no-bypass rule) --
  - docs/_config.yml (hardcoded GitHub URL pattern)
  - install.sh (chown/path/URL literals)
  - .claude/skills/claims-audit/generate_report.py (flake8/print())
  - .github/workflows/slm-migration-gate.yml (hardcoded :5432)
  - autobot-backend/services/knowledge/code_indexer_test.py (26 pre-existing
    blocking-I/O-in-async findings)
  - autobot_shared/user_management/models/core_test.py (pre-existing mypy
    strict errors on importlib.util.module_from_spec's Optional return)
Each needs its own debt fix before its branch-name reference(s) can be renamed.

Dated historical records (docs/archives, changelog/, docs/research,
docs/superpowers/plans+specs, docs/audit, docs/adr, docs/prd, docs/planning,
docs/analysis, docs/design, docs/discovery, and auto-generated
docs/verification*.json/md, docs/system-state.md) are left untouched.

* test(migrations): say where the cascade tests' INSERT names come from (#16464)

Review nit on #16467: the nosec justification said the names come from the schema; only the columns do -- the table is a literal from this module.

* test(migrations): fill every required organizations/users column from the schema (#16464)

migration-tests at eb2d22d: 1 failed, 159 passed. The organization
cascade test inserted an organizations row without kb_inheritance_weight,
which 20260616_060 adds NOT NULL and then strips of its server default, so
the insert raised NotNullViolationError before any cascade was exercised.

The activity-table inserts already read their required columns from
information_schema; the organizations and users inserts were still
hand-written and so drift whenever a migration adds a required column.
_insert_row now serves all of them: every NOT NULL column without a
default that the caller did not supply gets a typed placeholder, and an
unknown type still fails by name. double precision joins the placeholders.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

infra(git): swap branch names across the repo for the rename (in-repo half of #16461)

1 participant