Skip to content

feat(git-sync): ask "what is this repository?" at create (trinity-enterprise#704) - #3022

Merged
dolho merged 35 commits into
devfrom
feature/ent704-create-kind-ui
Oct 5, 2026
Merged

dolho merged 35 commits into
devfrom
feature/ent704-create-kind-ui

Conversation

@dolho

@dolho dolho commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

⚠️ Merge order: after #3020, which itself follows #3015 → #3016 / #3017 / #3018. This branch is stacked on #3020, so until those merge the diff against dev includes their commits. This PR's own change is the last commit, 94301a8b. It is independent of #3021.

Summary

The UI and manifest half of trinity-enterprise#704. trinity-enterprise#705 (#3020) added the create-time kind (agent / deployment) and the git_mode result to the API. This PR asks the question where people create agents, and shows the result.

  • Create modal: AgentKindPicker.vue asks "What is this repository?" with two answers, An agent or A deployment of a codebase.
    • It is asked exactly when the create binds git: a GitHub template from the list, or a custom repository with the clone intent.
    • It is never asked for blank or local agents, copy, fork, or a fork-to-own template. Those either have no git link or are an agent in your own repo by definition.
    • Unasked, no kind is sent, so the API default applies.
  • After create: ImportValidationStep renders GitModeNotice.vue from the create response's git_mode. When an agent fell back to pull-only, it says so plainly and gives the reason (status-warning tokens).
  • Git panel: GitBindingBadge.vue shows Agent · own branch or Pull-only. It reads a new db_config.source_mode on GET /api/agents/{name}/git/status.
  • System manifest: per-agent kind: is a recognised key, so it no longer triggers an unknown-key warning. deploy_manifest passes it to create. An unset kind stays None, so the create default applies.

Tests

  • src/frontend/tests/unit/createAgentKind.spec.js (mounted, jsdom), 8 tests:
    • which create paths ask the question
    • the answer reaching the createAgent payload
    • git_mode reaching the post-create step
    • the notice text
    • the badge
  • tests/unit/test_2373_system_endpoints.py: manifest kind is parsed without a warning; an out-of-range value is rejected.
  • tests/unit/test_ent125_resilient_system_deploy.py: the declared kind reaches the create call; an undeclared one stays None.
  • tests/unit/test_ent704_git_status_binding.py: db_config.source_mode for both bindings.
  • Mutation check: I reverted the manifest parse and the deploy passthrough, and all 3 manifest tests went red. The frontend spec was mutation-checked on the picker gate and the payload line.
  • Full frontend unit suite 3638/3638 at authoring, plus the raw-colour, loading-gate and source-text ratchets and check:tokens. Related backend suites: 148 passed.

Docs

Related to abilityai/trinity-enterprise#704

🤖 Generated with Claude Code

dolho and others added 3 commits September 25, 2026 15:52
…rise#703)

Invariant G3: human and fleet work reaches the agent within a bound.
Nothing inside the container ever pulled; the 2026-09-24 audit found
agents up to 31 commits behind.

- agent server: a pull loop beside the push loop, gated per cycle on
  the owner's pull_sync_enabled (read live, GIT_SYNC_PULL fallback),
  interval GIT_SYNC_PULL_INTERVAL_SECONDS (defaults to the push one).
  Under _REPO_LOCK, never while an execution runs (checked again right
  before the tree is touched). Fast-forward, or rebase aborted on
  conflict. Uncommitted edits are stashed explicitly and a pull that
  collides with them is undone - not --autostash, which strands them
  in the stash while reporting success.
- pull_sync_enabled + last_pull_at/_status/behind_after_pull on both
  migration tracks; backfill on only where auto-sync is on; new github
  agents get it at creation (source mode included), GIT_SYNC_PULL env
  derived from the DB flag alone at recreate.
- GET/PUT /api/agents/{name}/git/pull-sync; sync-health persists the
  pull outcome (bounded); Settings -> Git sync gains the toggle.

Stacked on #3020 (+#3015-#3018): merges after it.

Related to Abilityai/trinity-enterprise#703

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…erprise#704)

The UI and manifest half of the create-time kind that trinity-enterprise#705
added to the API.

- Create modal: AgentKindPicker asks "an agent" or "a deployment of a
  codebase" exactly when the create binds git (a GitHub template from the list,
  or a custom repo with the clone intent). Never for blank/local, copy, fork or
  fork-to-own. Unasked, no kind is sent.
- After create: GitModeNotice renders the response's git_mode and says plainly
  when an agent was created pull-only, with the reason.
- Git panel: GitBindingBadge ("Agent · own branch" / "Pull-only") from the new
  db_config.source_mode on the git status.
- System manifest: per-agent `kind` is parsed (no unknown-key warning) and
  passed to create.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@dolho dolho added the ui PR touches the frontend UI — triggers Playwright e2e tests label Sep 25, 2026
…eSQL (trinity-enterprise#703)

The inline comment on `pull_sync_enabled` sat between the comma and the
FOREIGN KEY clause. `_PG_TABLE_SUBS` strips that clause only when it directly
follows the comma, so the clause survived without its REFERENCES and
PostgreSQL rejected the table ("syntax error at or near ')'"), failing 18
requires_postgres tests in schema-parity. The comment moves above the column.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vybe

vybe commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

merge-train: ejected from this train because it is stacked on #3020, which is ejected pending a ruling (see #3020). No conflict with #3021 (merge-tree clean).

Mechanical fix to fold in while it waits: CreateAgentModal.vue shows the post-create step only when githubSourced (github-custom || isForkToOwn). A GitHub template picked from the list shows the kind picker, but then the modal closes, so GitModeNotice never appears and the "Created pull-only" warning is lost on the path most likely to fall back. Tests otherwise green (57 backend, 28 vitest incl. ratchets).

@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

⚠️ Nightly unit-suite check skipped — merge conflict against dev.

Resolve by running git merge dev locally and pushing the result. The next nightly run will re-test once the conflict is gone.

@github-actions

Copy link
Copy Markdown

⚠️ Live-instance suite skipped — merge conflict against dev.

Resolve by merging dev locally and pushing the result; the next nightly re-tests.

…e notice (trinity-enterprise#704)

The modal swapped to the post-create step only for a custom repo or a
fork-to-own template, so a GitHub template picked from the list closed on
create and GitModeNotice never rendered. That is the path the kind picker is
shown on and the one most likely to come back pull-only, so the warning was
lost exactly where it mattered. githubSourced now keys on the template's
source; a local or blank create still closes straight away.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vybe

vybe commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

merge-train (2026-09-27): one commit pushed, the fix from my 09-25 note. a87f3f115: CreateAgentModal.vue now keys githubSourced on selectedTemplate.source === 'github', so a GitHub template picked from the list reaches the post-create step and GitModeNotice renders instead of the modal closing. Two tests in createAgentKind.spec.js: the list-template path (red before the fix: the validation step never rendered) and a guard that a local template still closes at once. 10/10 in the spec, ratchets green.

This PR still merges after #3020, which it is stacked on. #3020 is waiting on the probe-versus-ownership ruling.

dolho and others added 5 commits September 28, 2026 10:56
…nto feature/ent703-pull-heartbeat

# Conflicts:
#	src/backend/db/migrations.py
#	tests/registry.json
…ns, brings main to working branches (trinity-enterprise#703)

PR #3021 review:
- _with_stash wraps every post-stash step: a git child that times out
  (run_registered raises TimeoutExpired) goes back to the pre-pull HEAD
  and re-applies the stash; when that is impossible the error says the
  edits are kept in `git stash`.
- reset --hard's return code is checked. A failed undo stops with an
  error naming it instead of leaving UU files behind silently.
- Both cycles refuse to run over unmerged paths. The push cycle checks
  before `git add -A`, which would stage conflict markers and push them
  to origin as a successful sync.
- The execution gate counts register_pending entries (#2433), so a turn
  queued on the chat lock or the headless pool is busy, not idle.
- The pull reaps stale lock litter first, as the push cycle does; a
  pull-only agent has no push cycle to do it.
- sync-state gains last_pull_error streak fields: consecutive pull
  failures / skips and last_successful_pull_at.

Ruling on the intent question: a trinity/* working branch only ever
pulled itself, so human pushes to main never arrived (G3). The cycle
now also merges origin/main (via _get_pull_branch) into the working
branch — a merge, not a rebase, since the branch is already pushed; a
conflict is aborted and recorded.

Nine real-repo tests, all red before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… + UI copy (trinity-enterprise#703)

- Alembic 0076_pull_sync -> 0080_pull_sync <- 0079_telegram_group_context
  (one head, 81 revisions); SQLite entry re-appended after dev's.
- The same migration pair adds agent_sync_state.last_pull_error,
  last_successful_pull_at, consecutive_pull_failures and
  consecutive_pull_skips, persisted by the sync-health poller (bounded,
  coerced; a success clears the error). ent#706/#707 read these, so they
  land here rather than as a second migration on the same table.
- agent-runtime.md says three loops; the flow and requirement describe the
  main merge, the queued-turn gate, the unmerged-path refusal, what
  behind_after_pull measures, and that auto-sync agents already rebase in
  the push cycle.
- Settings copy no longer hard-codes 15 minutes
  (GIT_SYNC_PULL_INTERVAL_SECONDS) and no longer claims the push cycle
  never touches the tree while the agent works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n (trinity-enterprise#704)

Follows the #3020 ruling: the platform-wide GitHub token never earns the
working-branch default. The picker no longer promises one for any token
that can push, and no longer hard-codes the 15-minute interval.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dolho

dolho commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

6d7285457 re-merges #3020, which now carries dev and the probe-vs-ownership ruling. The merge is clean.

e83fe51f8 brings the kind picker in line with that ruling. The "agent" option now says it needs your own GitHub token with push access, and that the platform-wide token doesn't count. It no longer hard-codes the 15-minute interval. GitModeNotice's header comment says the same.

Tests: createAgentKind.spec.js 10/10, full vitest (ratchets included), and 119 backend tests across the #704/#2373/ent125/#1484 files. CI green. Still merges after #3020.

@AndriiPasternak31 AndriiPasternak31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is stacked on #3020 (its head 8b20c1714 is an ancestor), so I reviewed only this PR's own commits against it: 94301a8b4, a87f3f115, e83fe51f8, plus the 6d7285457 merge. The picker gating, the payload and the manifest passthrough are right. The problem is that the notice and the badge decide "pull-only" from source_mode alone, and fork-to-own agents are source_mode=true but do push. So both surfaces now tell every fork-to-own user something false.

  1. [blocking] src/frontend/src/components/GitModeNotice.vue:38, src/frontend/src/components/GitBindingBadge.vue:12: fork-to-own agents are shown as pull-only.

    • _apply_fork_to_own sets config.source_mode = True (crud.py:893), and _git_auto_sync_baked still bakes auto-push for it because fork_upstream is set. The agent pushes to its fork's default branch.
    • The create response for that path is {kind: "agent", source_mode: true}. kind defaults to agent because the picker is hidden on fork paths, so no kind is sent.
    • As a result, fellBack is true and the post-create step shows the warning-coloured "Created pull-only". Both fork paths reach that step: the custom-repo fork intent did already, and since a87f3f115, so does a featured fork-to-own template from the list. I mounted the notice with that payload and it rendered Created pull-only / source_mode set explicitly.
    • On the Git panel, the badge for the same agent says "Pull-only: this agent tracks the branch and never pushes to it."
    • Failure scenario: someone forks a template so it can keep its work, and the platform tells them it won't.
    • Fix: have the backend say whether the agent pushes rather than inferring it from source_mode. For example, add a pushes flag to git_mode from _git_auto_sync_baked, and on db_config either an equivalent flag or a fork marker. Then key fellBack, the headline and the badge on that flag. Add a fork-to-own case to createAgentKind.spec.js. It would have caught this.
    • Related, and belongs in #3020: the reason shown for a fork create is "source_mode set explicitly", not "fork-to-own: the agent owns its fork". Pydantic v2 adds the attribute that _apply_fork_to_own assigns to model_fields_set, so the explicit-source_mode branch in _apply_agent_kind_default fires first and the fork branch is unreachable. I checked this in the test venv. Now that this PR shows the reason text to users, it matters more.
  2. [should-fix] src/backend/services/system_service.py:1114 (export_manifest): kind does not round-trip.

    • This PR makes kind a manifest key, but export never writes it.
    • Failure scenario: export a system whose members were deployed as kind: deployment and redeploy it. The creator's own token can push, so those members come back as agents with working branches and auto-push into the product repos they were meant to only pull from.
    • The #2373 D3 tests treat export→redeploy round-trip as the contract.
    • Fix: emit kind: deployment for a source-mode, non-fork member, or persist kind, and add an export assertion. If you'd rather not do it here, call the gap out in system-manifest.md and open a follow-up.
  3. [nit] src/frontend/src/components/AgentKindPicker.vue:58: the "An agent" description is one ~60-word sentence joined by semicolons and dashes, with three separate caveats (own token, platform token doesn't count, use Fork for someone else's template). Splitting it into two short lines, or moving the caveats into the post-create notice, would make the choice readable at a glance.

  4. [nit] The deploy_system MCP tool describes the manifest format inline (src/mcp-server/src/tools/systems.ts:130-140) and doesn't mention kind. An agent composing a manifest through MCP won't know the key exists. One line there would fix that.

What I checked

  • Stack: git merge-base --is-ancestor against #3020's head. Reviewed the own-commit diff only (17 files).
  • Backend, run in the test venv with seeds 12345 and 99999: test_ent704_git_status_binding.py, test_2373_system_endpoints.py, test_ent125_resilient_system_deploy.py, test_1484_create_agent_characterization.py. 119 passed on both seeds.
  • Frontend: createAgentKind.spec.js plus the raw-colour and loading-gate ratchets, 30/30. I also ran a throwaway spec that mounted GitModeNotice/GitBindingBadge with a fork-to-own payload, which confirmed finding 1.
  • CI: 23 pass, 5 skipped.
  • Security: git_mode still rides the create response only, not the /ws broadcast. The new db_config.source_mode field is behind the existing agent-scoped auth on git status. No token handling or PAT-gate change in this PR's own commits, and no schema change.
  • Design contract: only semantic action-*/status-* tokens plus gray.

AndriiPasternak31 and others added 8 commits September 28, 2026 21:57
#3005 landed Alembic 0080_agent_skill_sets on 0079_telegram_group_context,
the same parent this branch's 0080_pull_sync used, so merging as-is would
leave two heads and `upgrade head` would apply nothing.

Renumber the revision to 0081_pull_sync, chained on 0080_agent_skill_sets
(file, revision, down_revision, docstring, the SQLite mirror note and the
revision test). SQLite MIGRATIONS keeps dev's agent_skill_sets entry first,
pull_sync after it. tests/registry.json keeps both entries. No logic change.
…nto feature/ent703-pull-heartbeat

# Conflicts:
#	tests/unit/test_1484_create_agent_characterization.py
…p merges (trinity-enterprise#703)

PR #3021 re-review:
- A conflict merging main was recorded as "Auto-merging <file>": git
  prints it on stdout with an empty stderr. Unmerged paths are read
  before the abort; the error is "diverged: merge conflict with main
  (<files>)", and a failed merge --abort is named.
- `git rebase` flattened the merge the pull made into copies of main's
  commits; both cycles now rebase with --rebase-merges.
- A failed strict ahead/behind count fails the pull instead of reading
  as up to date.
- A timed-out step is reset to the pre-pull HEAD even with nothing
  stashed; a reset blocked by the killed child's index.lock says so.
- "Never runs while the agent is working" is check-then-act: the copy
  and docs now say "never starts" and document the admission window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nto feature/ent704-create-kind-ui

# Conflicts:
#	docs/memory/requirements/github.md
…rt round-trips kind (trinity-enterprise#704)

PR #3022 review:
- Fork-to-own agents are source_mode=true but auto-push to their own
  fork, so GitModeNotice showed "Created pull-only" and GitBindingBadge
  "Pull-only" for every fork. The create response's git_mode now carries
  `pushes` (the _git_auto_sync_baked predicate the env is baked from)
  and the git status's db_config carries `pushes` (not source_mode, or
  auto-sync on); both components key on it. Fork-to-own reads
  "Agent · own repo".
- export_manifest writes `kind: deployment` for a pull-only git member,
  so export -> redeploy never hands a deployment the agent default.
- The kind picker's agent description is split into two short lines.
- deploy_system's manifest format documents `kind`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nto feature/ent703-pull-heartbeat

# Conflicts:
#	tests/registry.json
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dolho

dolho commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

Review of 09-28 addressed. 4a80801b3 and 82fcf2788 merge #3021, which now carries #3020's review fixes. The fixes are in 1935f3169, and 06840f0f6 updates the registry.

1. [blocking] Fork-to-own shown as pull-only. 1935f3169.

  • Backend:
  • Frontend:
    • GitModeNotice keys fellBack and the headline on pushes. It falls back to !source_mode only if an older backend omits the field. A fork now reads "An agent that owns its repository".
    • GitBindingBadge renders from pushes: Agent · own branch, Agent · own repo (fork-to-own) or Pull-only. GitPanel passes both fields.
  • Tests (all fail before the fix):
    • createAgentKind.spec.js has two mounted fork-to-own cases (notice and badge).
    • test_ent704_git_status_binding.py parametrizes pushes: working branch, working branch paused, fork-to-own, pull-only.
    • test_1484 asserts git_mode.pushes through the full create_agent_internal for an owned repo, a pull-only fallback and a real fork-to-own create. The fork create also asserts GIT_SYNC_AUTO=true and the fork reason.
  • Fork reason: fixed in feat(git-sync): an agent created as an agent owns its repository (trinity-enterprise#705) #3020 (d8a9fd0f8). The fork branch now runs before the explicit-source_mode branch, so a fork reports "fork-to-own: the agent owns its fork". This PR's fork create test asserts that end to end.

2. [should-fix] kind didn't round-trip through export. export_manifest now writes kind: deployment for a pull-only git member (source mode with auto-sync off). A pushing member, a fork-to-own member, or one with no git binding writes no kind.

  • This is the conservative direction: kind isn't persisted, so an agent that fell back to pull-only also exports as a deployment and stays pull-only on redeploy.
  • Test: test_export_round_trips_kind_so_a_deployment_stays_pull_only drives the real function with four members and re-parses the output.
  • system-manifest.md documents it.

3. [nit] Picker description. Split into two short lines: what an agent is, then "Needs a repository you own and your own GitHub token (Settings), or it is created pull-only. For someone else's template, choose Fork." This now also reflects #3020's owner == token-login rule.

4. [nit] MCP deploy_system. The inline manifest format now shows kind: deployment and what the two values mean. tsc --noEmit is clean.

Verification

  • Frontend npm run test:unit: 3714/3714, ratchets included. check:tokens OK. The new markup uses only gray and existing semantic tokens, so the raw-colour baseline is unchanged.
  • Backend, 35 files (ent704, 2373, ent125, 1484, fork-to-own, ent703, 3010, 3011, 2107, ent109, ent705, models-centralized, schema/alembic/migrations, sync health): 799 passed and 3 skipped on seeds 12345 and 99999.
  • Single Alembic head: 0081_pull_sync.
  • Not checked in a browser: I checked the badge and notice copy by mounting them, not in a live UI in both themes. No layout or colour classes changed.

🤖 Generated with Claude Code

…, wrap header, name the auto-sync toggle limit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dolho

dolho commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

@obasilakis, your non-blocking points are addressed in the latest commit on this branch.

  • The pushes inference limit: system-manifest.md now has a "Known limit" paragraph. It explains that export treats "source mode + auto-sync on" as fork-to-own, so a deployment whose owner turns auto-sync on exports with no kind, and its badge says it saves to its default branch. Rejecting that toggle properly needs a persisted fork marker, which agent_git_config doesn't have yet. That's for a follow-up.
  • Nits: the gitMode prop comment in ImportValidationStep.vue now lists pushes, and the long header line in GitModeNotice.vue is wrapped.

Also since your approval: the branch has merged the updated #3021, so it carries current dev and #3021's 0081_pull_sync → 0082_pull_sync renumber. Single head, both migration tracks updated.

@AndriiPasternak31, the 09-28 changes-requested items were addressed in 1935f3169 (see the 09-29 comment above), and obasilakis has approved since. Could you re-review, or dismiss your review if you're satisfied?

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

✅ Alembic head check clear — merging this PR into dev leaves one head (0088_skill_gate_requests).

Previously flagged; resolved.

Evaluated on the version line only — this PR also conflicts with dev in 6 unrelated file(s), which do not change this verdict but must be resolved before merge:

docker/base-image/agent_server/auto_sync.py
docker/base-image/agent_server/routers/git.py
docs/memory/requirements/github.md
src/backend/db/migrations.py
src/frontend/src/components/GitSyncSettingsPanel.vue
tests/unit/test_1484_create_agent_characterization.py

Advisory — this check does not block merge. · head_sha: 1455fcf008abab9f37f960d88c2104852255c2a8 · run

@AndriiPasternak31 AndriiPasternak31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the 09-28 points are addressed. Re-checked at d43337aa6.

  1. [was blocking] Fork-to-own shown as pull-only: fixed. git_mode.pushes is now the same _git_auto_sync_baked predicate the env is baked from (crud.py:1582-1593), so the notice and the container can't disagree. db_config.pushes is at routers/git.py:135. GitModeNotice.vue and GitBindingBadge.vue key on pushes, and fork-to-own reads "An agent that owns its repository" / "Agent · own repo". Mounted fork-to-own cases are in createAgentKind.spec.js. The unreachable fork reason is fixed upstream in #3020 (d8a9fd0f8) and asserted end to end in test_1484.

  2. [should-fix] kind round-trip: fixed for the normal case, one residual. export_manifest writes kind: deployment for source-mode members with auto-sync off (system_service.py:1194-1206), and the new round-trip test re-parses the export. The residual is the "Known limit" you documented in system-manifest.md. PUT /git/auto-sync (routers/git.py:1188) has no source-mode guard, so an owner who turns auto-sync on for a deployment gets two wrong results:

    • The badge says "saves its work to its default branch" while the heartbeat refuses to push.
    • Export drops kind. A redeploy by a creator who owns the repo and has their own token then gets a working branch plus auto-push. That's the original failure, now reachable through one owner-side toggle.

    Documenting it is fine for this PR, but please file the follow-up (a persisted fork marker on agent_git_config, then reject the toggle for non-fork source-mode agents) and link it from the Known-limit paragraph. I couldn't find an open issue for it.

  3. [nit] Picker copy: fixed. Split into desc + note (AgentKindPicker.vue:59-60).

  4. [nit] MCP deploy_system format: fixed. kind documented (systems.ts:137).

Before merge (not code in this PR):

  • Alembic head fork vs current dev. dev now has 0082_agent_sync_state_divergence (#3035). This branch carries #3021's 0082_pull_sync, which also chains off 0081_portal_messages_unread_idx, so that's two heads, and upgrade head would apply nothing (Invariant #3; the alembic-head-watch comment shows it). The fix belongs in #3021: rechain 0082_pull_sync → 0083_… off 0082_agent_sync_state_divergence on both tracks. Then re-merge here.
  • CONFLICTING with dev: requirements/github.md, db/migrations.py, db/schema.py, db/sync_state.py, db/tables.py, sync_health_service.py, tests/registry.json. Most of these come from the #3021/#3035 overlap.

What I ran (worktree at d43337aa6):

  • Backend: test_ent704_git_status_binding.py, test_2373_system_endpoints.py, test_1484_create_agent_characterization.py, test_ent125_resilient_system_deploy.py. 136 passed on seed 12345; also green on seed 99999.
  • Frontend: createAgentKind.spec.js plus the raw-color and loading-gate ratchets, 32/32.

# that population (creation turns auto-sync on for a source-mode
# agent only when it forked); a working branch pushes even while
# its auto-sync is paused (operator Push).
"pushes": (not git_config.source_mode) or bool(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pushes = not source_mode or auto_sync_enabled is right today, but it's an inference. set_auto_sync_config (L1188) lets a deployment's owner flip it, and then this says "pushes" for an agent the heartbeat won't push from. Please link the follow-up issue in this comment.

# mode AND auto-pushes) exports as a deployment, so a redeploy never
# hands it the agent default's working branch + auto-push. An agent
# that pushes, or has no git binding, exports no `kind` (the default).
try:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same inference as git.py:135. With auto-sync toggled on, a deployment exports with no kind and redeploys as an agent. The known limit is documented, so this is fine for now. Please link the follow-up issue.

dolho and others added 4 commits September 30, 2026 10:38
… revision to 0083

dev gained 0082_agent_sync_state_divergence (#3035), which adds its own
agent_sync_state columns. Union both column sets across schema/tables/
sync_state/sync_health_service, chain 0083_pull_sync off dev's head, and
order the SQLite entry after agent_sync_state_divergence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2996's route census (merged to dev) requires every new route to be
classified. The agent's pull loop reads GET .../git/pull-sync with its
own key each cycle (AGENT_CALLABLE); the PUT is a setting write, so it
takes Depends(require_person) like the other #2996 settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vybe

vybe commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

merge-train: not on this train. It is blocked on #3021, which it contains in full, including #3021's open data-loss path. This PR's own delta has no criticals, and its kind field can't get around the PAT gate (it goes through _apply_agent_kind_default).

Items to consider once #3021 is fixed:

  • Badge vs create response (routers/git.py:136-137): pushes = (not source_mode) or auto_sync_enabled says a tokenless working-branch creator "saves its work there", but the create response says pushes=False.
  • Export drops the agent intent (system_service.py:1194-1206): a kind: agent member that fell back to pull-only is exported as kind: deployment. That errs in the safe direction.
  • Mechanical:
    • GitBindingBadge.vue should compose BaseBadge.
    • GitModeNotice.vue uses dark:text-status-warning-300, but the contract says 400.
    • db_config.source_mode/pushes aren't documented in api-endpoints.md.

dolho and others added 2 commits October 1, 2026 10:08
dev moved past 0082 (0083 to 0085 landed), so 0083_pull_sync forked the
Alembic graph into two heads, which alembic-head-watch flagged. It is now
0086_pull_sync on 0085_ent720_email_identity, and the SQLite list keeps both
sides, with dev's entries first and pull_sync after. The merge also brings
#3107, the agent-server boot fix whose absence failed journey-smoke.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dolho and others added 2 commits October 2, 2026 12:36
…estatement (#3021)

dev gained 0086_metric_points_restatement off 0085, so this branch's
0086_pull_sync was a second head and alembic-head-watch failed. Renamed
to 0087_pull_sync and re-parented; the SQLite list keeps dev's entry
first, matching the Alembic order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@dolho dolho left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — CI fixed, one UX issue worth fixing before merge

CI: alembic-head-watch was red because dev gained 0086_metric_points_restatement off 0085, making the stacked 0086_pull_sync (from #3021) a second head. Fixed on #3021 (renamed to 0087_pull_sync, re-parented onto 0086_metric_points_restatement) and merged into this branch (0d4615924). Locally: check_alembic_heads → 1 head, check_alembic_parity PASS; submodule pointers equal dev's.

Overall: solid. pushes comes from one predicate (_git_auto_sync_baked), the Git panel/status rule and the export rule are exact complements, so fork-to-own no longer reads as pull-only. No new endpoint; the ent#162 PAT-tier gate in _apply_agent_kind_default is unchanged.

Medium — the kind picker offers an answer that cannot happen on list templates

CreateAgentModal.vue:438-441 (showKindPicker) shows the picker for every source === 'github' list template, defaulting to "An agent — saves its work to its own branch". But every list template is a catalog entry: crud.py:1595 passes catalog_template=True, and _apply_agent_kind_default (crud.py:981) then always returns pull-only ("a shared catalog template: pull-only. Fork it…"). So a creator with their own PAT picks the default and always lands on the amber "Created pull-only" notice. The agent option's note says "choose Fork", but non-required list templates have no fork option here.
Fix (either): show the picker only for github-custom + clone (the one path where "agent" can produce a working branch); or on the list path default to deployment and change the agent option's note to "Catalog templates are always pull-only — fork to keep this agent's work in git". createAgentKind.spec.js ("is asked for a GitHub template, defaults to an agent") pins the current behaviour and would move with it.

Low

  • Export collapses "asked for agent, fell back" (system_service.py:1194-1206): an agent created kind=agent that fell back to pull-only exports as kind: deployment, so a redeploy after the creator adds a token stays pull-only. Safe direction and documented; worth a line in the PR description (or persist kind later).

Nits

  • GitBindingBadge.vue:335 — fork-to-own with auto-sync off shows "Pull-only … never pushes to it", but an operator Push may still work; "auto-sync off" would be truer.
  • ImportValidationStep.vue:39 — the notice sits between the h3 and the copy-provenance line; putting it after keeps the heading and its subtitle together.
  • GitModeNotice.vue:386 — falls back to !source_mode when pushes is absent (older backend), the exact misread this PR fixes; a neutral "unknown" headline would be more honest.
  • List GitHub templates now go through ImportValidationStep (compatibility check after /info, CreateAgentModal.vue:287) — intended, but beyond the issue's stated scope; one line in the description.

Checked clean: semantic status-warning-* / action-primary-* tokens in both themes (raw-colour ratchet passes), native radio group in fieldset/legend, invalid manifest kind → 400 / preview failure, MCP systems.ts example updated (Invariant #13), backend tests cover fork-to-own pushes=True and the status binding. createAgentKind, rawColorRatchet, loadingGateRatchet specs: 32/32 pass.

🤖 Generated with Claude Code

dolho and others added 2 commits October 2, 2026 17:26
…tarving each other (#3021 review)

The two background loops started together on one interval and took
_REPO_LOCK non-blocking, so the loser skipped silently every tick and
the effective pull bound could quietly double. Background cycles now
wait up to GIT_SYNC_LOCK_WAIT_SECONDS (default 120 s) for the lock, and
the pull loop's first tick is half an interval after the push loop's.
Operator endpoints keep their immediate 409.

The pull's reset --hard undo re-checks that no execution started
meanwhile; if one did, the tree is left as it is (conflict markers block
the next push and pull) instead of discarding the turn's writes.
merge --abort runs only when MERGE_HEAD exists, so a merge that refused
to start no longer records "There is no merge to abort".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vybe

vybe commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

merge-train (2026-10-02): not on this train. #3021 merges today. This PR rides the next train once fixed, and it will need dev merged in after #3021 lands. I've set status-needs-fix, and your next push clears it.

Needs your call: your own 09:47 finding is still open at 1455fcf00.

  • CreateAgentModal.vue showKindPicker (~:438) shows the picker for every source === 'github' list template, with "An agent" as the default.
  • Every list template is a catalog entry, so crud.py:1595 passes catalog_template=True, and _apply_agent_kind_default (crud.py:981) returns pull-only before it probes push access. Reproduced with kind="agent", a per-user token and catalog_template=True: the result is source_mode=True, "shared catalog template", and the push probe is never called.
  • So the default always lands on the amber "Created pull-only" notice.
  • The two fixes are different UX, so they're yours to choose:
    1. Show the picker only for github-custom + clone.
    2. Default to deployment on the list path and add a note.
  • The list-template test mocks git_mode with a "no GitHub token" reason, which is why this stayed green. Please make the test drive the catalog path.

Mechanical, for the same push:

  • GitBindingBadge.vue: compose BaseBadge variant="neutral" instead of the hand-rolled <span> (design-system contract §primitives). title and data-testid pass through the single root.
  • GitModeNotice.vue: dark:text-status-warning-300 → -400 (contract: dark status text is the 400 tier, bug: text contrast below WCAG AA on nav badge and secondary labels (both themes) #2201).
  • docs/memory/architecture/api-endpoints.md: one line under GET /api/agents/{name}/git/status saying db_config carries source_mode and pushes (not source_mode or auto_sync_enabled, ent#704).
  • File the follow-up @AndriiPasternak31 asked for: a persisted fork marker on agent_git_config, then reject the auto-sync toggle for non-fork source-mode agents. Link it as (#N) from the "Known limit" paragraph in feature-flows/system-manifest.md and the routers/git.py:~136 comment. Neither tracker has it today.

Verified at this head: createAgentKind + ratchet vitest 32/32; test_ent704_git_status_binding, test_2373, test_ent125, test_1484 136/136. Nothing critical in this PR's own delta. The badge-vs-create-response point from 09-30 is moot: _gate_tokenless_request (crud.py:661) 400s a tokenless working-branch create first.

@vybe vybe added the status-needs-fix PR has an unaddressed review/validation finding; cleared by the author's next push (#2815) label Oct 2, 2026
@vybe

vybe commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

@dolho still outstanding from 10-02 (no push since the status-needs-fix):

dolho and others added 2 commits October 5, 2026 09:36
…kind-ui

# Conflicts:
#	docker/base-image/agent_server/auto_sync.py
#	docker/base-image/agent_server/routers/git.py
#	docs/memory/requirements/github.md
#	src/backend/db/migrations.py
#	src/frontend/src/components/GitSyncSettingsPanel.vue
#	tests/unit/test_1484_create_agent_characterization.py
…an matter (#3022 review)

Every list template is a catalog entry, which _apply_agent_kind_default
always makes pull-only, so the kind picker there defaulted to an outcome
that could not happen. It now shows only for a custom-repo clone.

Review nits: GitModeNotice stays neutral when the response lacks
`pushes` instead of guessing from source_mode; GitBindingBadge says
pull-only is about auto-sync; the notice sits after the provenance line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dolho

dolho commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up to the 10-02 review:

  • Merged dev (806b538bf). The conflicts were all in feat(git-sync): the container pulls origin on its own (trinity-enterprise#703) #3021's files, which had since been squash-merged. Each one was resolved as dev's version plus this PR's own delta. check_alembic_heads → 1 head (0088_skill_gate_requests).
  • Medium, the kind picker on list templates (76c5470eb): the picker now shows only for github-custom + clone. That's the one path where "An agent" can produce a working branch. Every list template is a catalog entry and goes pull-only under _apply_agent_kind_default, so no kind is sent for it. createAgentKind.spec.js was changed first and went red, then green. requirements/github.md and the github-sync flow were updated to match.
  • Nits:
    • GitModeNotice stays neutral when pushes is missing; it no longer guesses from source_mode.
    • The GitBindingBadge title now says pull-only refers to auto-sync.
    • The notice moved after the provenance line.
  • Tests: vitest for createAgentKind, rawColorRatchet and loadingGateRatchet: 34/34 pass. Backend tests for the create, system, binding and pull-sync files: 212 pass.

Not done: the Low item about export collapsing "asked for agent, fell back to pull-only". It's still documented behaviour.

🤖 Generated with Claude Code

@github-actions github-actions Bot removed the status-needs-fix PR has an unaddressed review/validation finding; cleared by the author's next push (#2815) label Oct 5, 2026
@dolho
dolho merged commit 09f9d08 into dev Oct 5, 2026
29 checks passed
@dolho

dolho commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

/review — automated pre-landing review (at 76c5470eb53fb39891b1d1b15601ce63d6cb0641)

Post-merge. This PR merged into dev at 09:36 UTC today (merge commit 09f9d0868), so git merge-base origin/dev HEAD is the head itself. The diff reviewed is what the merge actually introduced: 09f9d0868^1..09f9d0868, 23 files, +723/−36. #3015–#3018, #3020 and #3021 had all landed earlier, so that range is this PR's own delta plus its conflict resolutions.

Branch: feature/ent704-create-kind-ui → dev
Files Changed: 23 (+723/−36)
Scope: DRIFT DETECTED. The dev merge 806b538bf reverted wording that #3021 had corrected. See I1.
Plan Completion (trinity-enterprise#704 per the PR body): 5 done, 0 partial, 0 not done, 1 changed, 1 unverifiable.

  • DONE: picker on the git-binding create path (CreateAgentModal.vue:441); kind in payload (:538); git_mode → post-create notice (:340, ImportValidationStep.vue:50); Git panel badge (GitPanel.vue:210, routers/git.py:126-137); manifest kind parse/deploy/export (system_service.py:59,166,1194-1206,1950).
  • CHANGED: the picker is now asked only for github-custom + clone, not for list templates (76c5470eb). The deviation is deliberate and documented in requirements/github.md and github-sync.md.
  • UNVERIFIABLE: both-theme rendering in a live UI (the author says it was checked by mounting only).

Execution coverage (Step 2.5)

changed symbol / test file executed by live consumer verdict
showKindPicker / payload.kind (CreateAgentModal.vue:441,538) createAgentKind.spec.js (mounted, jsdom) CreateAgentModal.vue:266 ✅ executed
githubSourced → postCreate.gitMode createAgentKind.spec.js CreateAgentModal.vue:337 → ImportValidationStep ✅ executed
GitModeNotice.vue pushes/fellBack/headline createAgentKind.spec.js (mounted) ImportValidationStep.vue:50 ✅ executed
GitBindingBadge.vue createAgentKind.spec.js (mounted) GitPanel.vue:210 ✅ executed
db_config.source_mode / .pushes (routers/git.py:126-137) test_ent704_git_status_binding.py (calls the handler) GitPanel.vue:210 ✅ executed
git_mode["pushes"] (crud.py:1609-1613) test_1484_… ×3 through create_agent_internal GitModeNotice.vue:435 ✅ executed
manifest kind parse / deploy / export test_2373_… ×3, test_ent125_… ×1 (real functions) deploy_manifest → AgentConfig.kind ✅ executed

Source-text grep over the changed tests: no hits.

Fix mutations, each reverted in a scratch copy:

  • (a) Re-widened showKindPicker to include list GitHub templates. Red: "is not asked for a catalog GitHub template, which is always pull-only".
  • (b) Restored the pushes ?? !source_mode guess in GitModeNotice. Red: "stays neutral when the response does not say whether the agent pushes".

The obasilakis 09-29 review already reported 11/11 mutations red for the earlier fixes.

Tests run at this head:

  • Backend: test_ent704_git_status_binding, test_2373_system_endpoints, test_ent125_resilient_system_deploy, test_1484_create_agent_characterization. 136 passed.
  • Frontend: createAgentKind + rawColorRatchet + loadingGateRatchet + sourceTextRatchet. 42/42 passed.

Critical Findings (block merge)

None.

Informational Findings (review required)

[I1] Scope / conflict resolution: the dev merge reverted #3021's honest data-loss disclosure, so user-facing copy and docs now overclaim (Confidence: 9/10)

Files (all on dev now):

  • src/frontend/src/components/GitSyncSettingsPanel.vue:76
  • docker/base-image/agent_server/routers/git.py:1180-1182, 1257-1258
  • docker/base-image/agent_server/auto_sync.py:187-188
  • docs/memory/requirements/github.md:~901

Evidence. This PR's merge diff replaces #3021's final wording (squash c3ba98a63) with the older pre-review text:

-          agent is working or has a turn queued, and a conflicting pull is
-          undone with the agent's edits put back. Edits made outside agent
-          turns (uploads, terminal) while a pull runs are not protected. ...
+          agent is working or has a turn queued, and never discards its own
+          changes. ...
-    - Refuses to run over unmerged paths. An undo never resets over a
-      registered execution (`_safe_to_reset`); writes outside the process
-      registry (Files API, docker exec, web terminal) made during the
-      integrate window are not protected. ...
+    - Refuses to run over unmerged paths. Local work is never discarded; ...

The code did not change. _safe_to_reset (agent_server/routers/git.py:595) still says reset --hard "discards every tracked-file write since the stash" and guards only registered executions. Files API, terminal and docker exec writes made during the integrate window can therefore still be lost.

Issue: none of these lines are part of #704. They come from the conflict resolution in 806b538bf ("Merge remote-tracking branch 'origin/dev'"), which took the branch side instead of dev's side on the #3021 files. The author's 10-05 comment says each conflict was resolved "as dev's version plus this PR's own delta", but for these four hunks it wasn't. The Settings panel now makes the exact promise that #3021's review asked to be withdrawn.

Fix: a small follow-up PR against dev that restores c3ba98a63's text in all four places. git show c3ba98a63 -- <file> holds the intended wording. No code change is needed.

Why: an operator who trusts "never discards its own changes" may upload or terminal-edit during a pull and lose work without warning.

[I2] Design-system contract: GitBindingBadge.vue hand-rolls a badge instead of composing BaseBadge (Confidence: 8/10)
File: src/frontend/src/components/GitBindingBadge.vue:11-16
Evidence: <span ... class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300". The contract (design-system-contract.md:27) lists BaseBadge and says "Never hand-roll a lookalike". components/base/BaseBadge.vue:32 has a neutral variant.
Suggestion: <BaseBadge variant="neutral" :title="title" data-testid="git-binding-badge">{{ label }}</BaseBadge>. vybe raised this on 10-02 and it is still unaddressed.

[I3] Docs: db_config.source_mode / pushes not documented in the API catalog (Confidence: 8/10)
File: docs/memory/architecture/api-endpoints.md has no entry for the new db_config fields on GET /api/agents/{name}/git/status. Grepping for git/status there finds no line that mentions them.
Suggestion: add one line: db_config carries source_mode and pushes (not source_mode or auto_sync_enabled, ent#704). Raised 10-02 and still open.

[I4] Known limit has no tracking issue (Confidence: 8/10)
File: docs/memory/feature-flows/system-manifest.md (Known limit paragraph) and routers/git.py:131-137.
Evidence: pushes = (not source_mode) or auto_sync_enabled infers fork-to-own. PUT /git/auto-sync accepts the toggle on a deployment, after which the badge says it saves to its default branch and export drops kind: deployment. No issue matching "fork marker" exists in either tracker, and the paragraph links none.
Suggestion: file the follow-up that AndriiPasternak31 and vybe asked for (persisted fork marker on agent_git_config, then reject the auto-sync toggle for non-fork source-mode agents) and link it as (#N) from both places.

[I5] Process: PR body links the issue with Related to, not Fixes (Confidence: 7/10)
Evidence: PR body line 36 reads Related to abilityai/trinity-enterprise#704. vybe asked on 10-03 for Fixes. The PR is merged, so ent#704's status-in-dev / closure now has to be set by hand.

[I6] Test hygiene: duplicated helper in test_ent704_git_status_binding.py (Confidence: 6/10)
File: tests/unit/test_ent704_git_status_binding.py:46-58. test_git_status_db_config_carries_the_binding re-inlines the monkeypatch that _status() (:33-42) already provides. Cosmetic only.

Prior review findings (status at 76c5470eb)

Source Finding Status Evidence
10-02 review, Medium (GitHub shows it as dolho's COMMENTED review of 10-02 09:47; same content as the brief's "10-02 kind-picker" finding) Picker offered "An agent" on catalog list templates, which are always pull-only ✅ Resolved CreateAgentModal.vue:441 now reads form.template === 'github-custom' && importIntent.value === 'clone'. Mutation (a) above turns the new test red. crud.py:1595 catalog_template=bool(gh_template) confirms list templates are catalog.
10-02 Low Export collapses "asked agent, fell back" into kind: deployment ⚠️ Not done, by choice Author's 10-05 comment says so. Documented in system-manifest.md. Safe direction.
10-02 nit Badge title "never pushes" was misleading ✅ Resolved GitBindingBadge.vue:383: "auto-sync does not push its work". Pinned by a test.
10-02 nit Notice placed between h3 and the provenance line ✅ Resolved ImportValidationStep.vue:48-50: after the provenance </p>.
10-02 nit Notice guessed !source_mode when pushes was absent ✅ Resolved GitModeNotice.vue:435 pushes ?? null gives the neutral "Created from GitHub". Mutation (b) turns it red.
10-02 nit List templates now go through ImportValidationStep (beyond scope) ✅ Described PR body and github-sync.md describe the post-create path.
09-28 AndriiPasternak31 (blocking) Fork-to-own shown as pull-only ✅ Resolved (re-approved 09-29) crud.py:1609-1613 git_mode.pushes from _git_auto_sync_baked; routers/git.py:136. Mounted fork cases in spec.
09-28 (should-fix) kind round-trip on export ✅ Resolved, with a known limit system_service.py:1194-1206. Limit tracked in I4.
09-28 nits Picker copy; MCP deploy_system doc ✅ Resolved AgentKindPicker.vue:247-248; systems.ts:137.
vybe 10-02 mechanical BaseBadge; api-endpoints.md line; follow-up issue; Fixes in body ❌ Open I2, I3, I4, I5.
vybe 10-02 mechanical dark:text-status-warning-300 → -400 ⚠️ Arguable, not changed GitModeNotice.vue:418. Contract :20 says dark status text is 400, but :9/:32 prescribe 300 text on a dark tinted ground, which is this case. Left to the design owner.
alembic-head-watch Two heads ✅ Clear Bot reports one head (0088_skill_gate_requests).

Clean Categories

  • SQL & data safety: no SQL or schema change. export_manifest reads db.get_git_config inside try/except with a warning (system_service.py:1200-1206).
  • Race conditions: none introduced. will_push is computed once and reused (crud.py:1609,1624).
  • Auth boundaries: no new endpoint. db_config fields ride the existing agent-scoped get_git_status. git_mode stays on the create response only, not on /ws (feat: agent-reported structured reports via MCP + dashboard display #918). Manifest kind goes through _apply_agent_kind_default, so the ent#705 PAT gate is unchanged. Out-of-range kind gives a ValueError (test test_manifest_kind_outside_the_two_values_is_rejected).
  • Credential exposure: none. The test PAT is a placeholder.
  • Enterprise disclosure (4.5): the guard pattern over added docs/ lines finds 0 hits.
  • Enum completeness: kind is Literal["agent","deployment"] (models.py:1266), and _KNOWN_AGENT_KEYS was updated.
  • Invariant feat: SMARTS trading pipeline with Telegram notifications and Miro visualization #13 (MCP): systems.ts manifest example updated.
  • Frontend tokens / ratchets: only gray, action-primary-* and status-warning-*. Raw-colour and loading-gate ratchets pass. No v-html.

Summary

  • Critical: 0 — none found
  • Informational: 6 — I1 should be fixed promptly as a small follow-up PR because the reverted copy is live on dev; I2–I4 are the outstanding 10-02 mechanical items
  • Scope: drift (I1, from the conflict resolution)

Suggested learning / deferred debt: after a stacked PR's base squash-merges, resolving the follow-on dev merge "branch side" on the base's files silently reverts review-driven changes the squash carried. Diff each conflicted file against the squash commit (git diff <squash> HEAD -- <file>) before committing the merge. (#3022 / 806b538bf vs #3021 c3ba98a63)

🤖 Generated with Claude Code

vybe pushed a commit that referenced this pull request Oct 5, 2026
…ollow-up) (#3226)

The dev merge 806b538 in #3022 resolved its conflicts on the #3021 files
by taking the branch side, which reverted #3021's (c3ba98a) review-driven
wording back to "never discards its own changes" / "never discards local
work". That is false: _safe_to_reset only spares registered executions, so
Files API, web terminal and docker exec writes made while a pull integrates
can still be lost.

Restores #3021's wording in the four places (Git sync settings panel copy,
_integrate_remote and _run_pull_once docstrings, the auto_sync pull-loop
comment, requirements/github.md) and keeps everything #3022 legitimately
added. Adds a mounted vitest assertion so the panel cannot regain the
claim. No behaviour change.

Related to #3022, #3021

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui PR touches the frontend UI — triggers Playwright e2e tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants