Skip to content

DO NOT MERGE — merge train: 3016,3017,3018,3025,3008 - #3027

Closed
trinity-ability wants to merge 16 commits into
devfrom
train/20260925-1608
Closed

trinity-ability wants to merge 16 commits into
devfrom
train/20260925-1608

Conversation

@trinity-ability

Copy link
Copy Markdown
Contributor

Integration surface for #3016, #3017, #3018, #3025, #3008. Never merged; members merge individually once green.

🤖 Generated with Claude Code

dolho and others added 16 commits September 24, 2026 17:39
…ivery failures reach REST and MCP callers (#2991)

`start_agent_internal` computed the skill-delivery result, and
`POST /api/agents/{name}/start` rebuilt its response from a whitelist that
left it out, so a caller could not tell a clean start from one whose assigned
skill failed or hit a name conflict.

- The endpoint returns `skills_injection` + `skills_result` beside the
  credentials pair. `skills_result` is a projection (`public_skills_result`):
  names, statuses and codes only — a per-skill error that carries an
  exception string, URL or path is reduced to a code (ent#334). A no-op start
  answers `skipped` + reason; a missing result reads `unknown`, never absent.
- A conflict keeps `success` (#2914), so `inject_assigned_skills` now names
  it in `conflicts` — distinguishable from a clean start in one response.
- MCP `start_agent` keeps its first line and, when delivery was not clean,
  adds the status and one line per skill that did not land.
- Same gap closed on `POST /api/system-agent/restart`; the fleet restart entry
  gains `skills_conflicts`. The projection is shape-defensive: it runs inside
  the start's try, so a raise would turn a start that happened into a 500.

Mutations: whitelist reverted (6 red), raw result passed through (5 red),
lifecycle drops conflicts (1 red), MCP returns only the message (2 red).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…efuses on a shared source-mode branch (#3011)

The heartbeat was add -A -> commit -> push origin HEAD with no fetch, so
the first foreign push to the agent's branch failed every later cycle
non-fast-forward, forever, with the agent's commits piling up locally.

- fetch origin <branch>; if behind, rebase --autostash onto it and push
  with --force-with-lease pinned to the fetched sha (a racing push is
  rejected, never overwritten); a plain push otherwise; a branch not yet
  on the remote is created by the push
- rebase conflict (or timeout): rebase --abort, repo left as it was,
  record 'diverged: rebase conflict on <branch>' for the existing
  sync_failing path; never resolve, overwrite or reset
- source-mode agent on the default branch (origin/HEAD, else main/master)
  refuses before committing: 'refused: source-mode on <branch>';
  fork-to-own agents (GIT_UPSTREAM_REPO or an upstream remote) exempt
- sync-state.json gains behind_after_fetch and last_successful_push_at

Fixes #3011

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PUT /git/auto-sync wrote the DB row and nothing else: the container gated
on GIT_SYNC_AUTO read once at startup, and every recreate re-derived it as
DB flag OR baked env. OFF never took effect on an agent that baked the
env at creation; ON waited for the next recreate.

- agent loop: starts whenever it can ask the platform and reads the
  owner's flag every cycle via GET /git/auto-sync with its own MCP key;
  OFF skips the cycle, ON runs it, no recreate. 404 'Git not configured'
  -> off; platform unreachable / 5xx / auth refusal -> the env fallback.
  /api/git/status reports the value the loop runs with.
- one writer: _apply_git_env_from_db derives GIT_SYNC_AUTO from the DB
  flag alone (OR + log removed); creation writes the flag from the same
  _git_auto_sync_baked predicate that bakes the env, ghosts included.
- one-shot backfill (SQLite + Alembic 0075): live non-source-mode ghosts,
  the env-true/DB-0 slice the DB can identify.
- Settings -> Git sync panel with both toggles (auto-sync, pause
  schedules while sync is failing).

Fixes #3010

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

Found on a live dev agent: the first cycle waits a full interval, so
/api/git/status reported the env fallback (off) for 15 minutes while the
owner's flag said on. Resolve once before the first sleep.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A Contents: read-only fine-grained PAT passed every check (ls-remote
talks to upload-pack; REST permissions.push is the user's role, not the
token's grant) and then failed every auto-sync for the agent's life.

- git_service.probe_push_access: git push --dry-run of a throwaway ref
  from an empty scratch repo, PAT via git_auth_env (never argv); asks
  receive-pack, creates nothing. ok / denied / transient.
- creation: agents that will auto-push (_git_auto_sync_baked) are probed;
  denied -> 400 naming GitHub's reason and the fix, before any branch is
  reserved or container created; transient -> logged, non-blocking.
- sync health: a sync_failing item whose error is a refused push is
  titled 'Git token can't push', says it won't recover on its own, and
  carries cause=push_denied + remediation.

Fixes #2107

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

CodeQL py/clear-text-logging-sensitive-data: the line comes from a child
that held the token. It is still returned (scrubbed) to the caller.

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

`_dual_ahead_behind_payload` measured the working tuple against
`origin/<current_branch>` only for `trinity/*` branches. Every other branch
got the `origin/main` counts under the working label. The fleet audit reads
`ahead_working` as unpushed commits, so a fleet renamed to `asus/*` reported
~9,000 unpushed commits while the true gap was 0.

- The working tuple uses `origin/<current_branch>` whatever the branch is
  named.
- With no upstream (never pushed, detached HEAD), `ahead_working` counts the
  commits no remote holds, and `behind_working` is null.
- A count that can't be computed is null, never 0. This covers the main tuple
  on a `master` repo with no `main`, which read 0 ahead for 7 days while one
  commit sat unpushed. The backend already stores null as 0, and the UI
  checks `> 0`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…mechanical, per the merge-train note on the PR

`ahead` aliases the main tuple, which this PR makes None on a repo with no
`main`; `None == 0` is false, so a clean `master` repo flipped from
"Synced" to "Changes pending". Restores dev's behaviour on that line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	docs/memory/architecture/agent-lifecycle.md
#	tests/registry.json
# Conflicts:
#	tests/registry.json
#	tests/unit/test_1484_create_agent_characterization.py
# Conflicts:
#	tests/registry.json
@vybe

vybe commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Train complete: #3016, #3017, #3018, #3025, #3008 merged individually (#3015 merged ahead of the train).

@vybe vybe closed this Sep 25, 2026
@vybe
vybe deleted the train/20260925-1608 branch September 25, 2026 16:59
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.

3 participants