Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ jobs:
- name: Install Redis for ledger integration tests
run: sudo apt-get update && sudo apt-get install -y redis-server

- name: Verify fleet admission with isolated Redis
run: |
redis_socket="$RUNNER_TEMP/byom-admission.sock"
redis-server --port 0 --unixsocket "$redis_socket" --save '' --appendonly no --daemonize yes
trap 'redis-cli -s "$redis_socket" shutdown nosave' EXIT
BRIDGE_TEST_REDIS_URL="$redis_socket" bun test src/bridge/fleet.test.ts

- name: Build service
run: bun run build

Expand Down Expand Up @@ -201,6 +208,11 @@ jobs:
node-version: 24.16.0
- run: npm ci
- run: npm run build
- name: Selected project root containment tests
run: |
command -v rg || brew install ripgrep
node --test dist/root-access.test.js
node --test --test-name-pattern='selected command|selected replay copy|programmatic probes reject' dist/native-sandbox.test.js
- name: Native environment containment tests
run: node --test dist/environment.test.js
- name: Native ACL and credential lifecycle tests
Expand Down
32 changes: 32 additions & 0 deletions docs/fork/patches.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,38 @@ unchanged.
- Delta: the port also picks up upstream `c688b30` (#225), which the fork's
byte-identical-to-v1.1.0 `release.yml` had been missing.

### Re-audit basis: upstream v1.2.0 integration (2026-09-18)

Recorded when the fork merged upstream release v1.2.0. Every disposition above
was re-checked against the merged tree; all ten behaviors remain Active and
none needed re-derivation.

- Fork ref and SHA: `uzh/main` at
`529d9c0ee18f0f4fb8e91ef726a2528db87335e8` (PR #25 release guard)
- Upstream ref and SHA: LibreChat-AI/code-interpreter tag `v1.2.0` at
`fd9a4fa65e0a5189957032c0046eb286311fda62` (also `upstream/main`)
- Merge base: `b35c503fd2fe7be412d95c0eef6db50a09aad280` (tag `v1.1.0`)
- Audited date: 2026-09-18
- Method: semantic merge of the exact refs above in the scratch clone (clean,
zero conflicts), file-overlap analysis between the fork's 55-file delta over
`v1.1.0` and the merge's 28-file delta, a logging-sink grep over the newly
introduced upstream files, and byte-checks of the release-automation files
- Delta: three upstream commits. `#226` (`4c7b224`, bounded
repository-instruction discovery) and `#222` (`95bfcbd`, selected coding
project registration) add new `packages/code` and `service` files; `#227`
(`672e195`) reports workspace admission capacity from `service/src/bridge`.
`#225` and `#233` were already ported (see the two bases above).
- Overlap: the only file both the fork delta and the merge touch is
`.github/workflows/ci.yml`, where upstream appends two test steps and the
fork's `chmod 0555` and release-version-resolution lines are unchanged. The
merged `.github/scripts/resolve-release-version.sh` and
`tests/release-version-resolution.sh` stay byte-identical to `v1.2.0`, and
`release.yml` differs from `v1.2.0` only by the fork guard described below.
- No merged upstream file introduces a logging sink, so the values-free policy
(below) gains no new surface.
- Limitation: the fork SHA identifies the pre-integration `main`; the
integration PR records the resulting exact head and the GitHub merge SHA.

States: Active, Review on sync, Draft, History only, Retired.

## Patch index
Expand Down
192 changes: 192 additions & 0 deletions docs/project/2026-09-18-upstream-v1.2.0-integration-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Upstream v1.2.0 integration plan

Status: executed — terminal condition met (green-CI draft PR #26 on the task
branch at head `a25ea9a`, ledger re-inventoried, slice and final reviews
closed with no findings); merging into `main` stays separately approved.
Package: full path (security seam: selected coding-project root access;
architecture seams: workspace admission capacity and repository-instruction
discovery)
Branch: chore/reconcile-upstream-v1.2.0
Target: uzh-bf/code-interpreter main
Upstream release: LibreChat-AI/code-interpreter v1.2.0 (tag `fd9a4fa`, also
`upstream/main`, released 2026-09-18)

## Approval summary

Fork `main` is at `529d9c0` (PR #25, release guard) and already carries two
of v1.2.0's five commits as ports: #233 (`fd9a4fa`, release version
resolution, cherry-picked as `b67791e`) and #225 (`c688b30`). The remaining
delta is three upstream commits: #226 (`4c7b224`) bounded repository
instructions for attached workspaces, #222 (`95bfcbd`) selected coding
project registration, #227 (`672e195`) workspace admission capacity
reporting.

The trial merge (`origin/main` + `v1.2.0`) is clean: zero conflicts, 28
files, +2427/−20, no lockfile or chart or Dockerfile change. The only file
both the fork deltas and the merge touch is `.github/workflows/ci.yml`,
where upstream appends two test steps and the fork's lines are untouched.
No merged upstream file adds a logging sink, so the values-free policy needs
no new sink. `release.yml`, `.github/scripts/resolve-release-version.sh`,
and `tests/release-version-resolution.sh` merge byte-untouched: the fork's
permanent release-job guard and the ported resolver survive.

All ten fork behaviors remain needed and none requires re-derivation. The
policy stays as agreed on 2026-09-18: the fork tracks upstream releases and
adds its own commits on top, deployments pin commit SHAs, and the fork never
cuts its own tags or publishes its own releases.

Done means: reconciled branch with the verification battery green at the
exact head, patch ledger re-inventoried to the new basis, reviews closed, and
a draft PR open with receipts. Deployment, image publication, GitOps
promotion, and merging into `main` are excluded here and separately gated.

## Evidence and binding contracts

### Live state (verified 2026-09-18)

- `uzh/main` = `529d9c0` (PR #25 merged 11:16:52Z as a merge commit). Fork
tags/releases remain 0/0. Post-merge CI run `35338850317` and image build
`35338850298` run on `529d9c0`; the `Release` workflow's only main-push
run (`35266235871`) failed before the fix, and every run after the job
guard is skipped, never failing.
- Upstream `v1.2.0` = `fd9a4fa` = `upstream/main`; delta to fork `main` is
the three commits above with `c688b30` and `fd9a4fa` already ported.
- Fork patch surface vs `v1.1.0`: 55 files (`git diff v1.1.0 origin/main`);
its intersection with the merge's 28 files is `ci.yml` only, and the
merged diff there is upstream's two appended test steps.
- New upstream code introduces no `console`/logger sink (grep over the new
service and packages/code files), so the values-free log policy (patch 9)
has no new surface to cover.
- The fork's GHCR image workflow, Helm chart, Dockerfiles, egress ledger,
queue-wait fallback, JWT trust table, telemetry seam, and PVC de-hook are
not touched by this merge.

### Fork patch disposition (vs v1.2.0)

| # | Behavior | v1.2.0 state | Disposition |
| --- | --- | --- | --- |
| 1 | Exact-SHA UZH GHCR images | no equivalent workflow | Keep; untouched |
| 2 | Spec-guard readable roots (chmod 0555) | rootfs-setup unchanged | Keep; untouched |
| 3 | Split/harden untrusted sandbox namespace | still single-namespace | Keep; untouched |
| 4 | Cede ownership to external controllers | chart unchanged | Keep; untouched |
| 5 | Argo-safe PVC package-init | hook still present | Keep; untouched |
| 6 | BullMQ poll fallback | waitForJobWithCancellation unchanged | Keep; untouched |
| 7 | Egress ledger indefinite reconnect | unchanged | Keep; untouched |
| 8 | JWT issuer-scoped trust table | unchanged | Keep; untouched |
| 9 | Values-free logging | no new sinks | Keep; untouched |
| 10 | Optional nonfatal telemetry | unchanged | Keep; untouched |

## Slices

S1 — Merge upstream v1.2.0 (main).
Merge `v1.2.0` into `chore/reconcile-upstream-v1.2.0` with the plan file as
the branch's first commit; keep upstream files byte-identical (the clean merge
does this natively) and the fork's release guard intact. Acceptance:
`git diff origin/main HEAD` equals the trial-merge delta, resolver files
byte-identical to `v1.2.0` plus the guard, `git diff --check` clean.

S2 — Ledger re-inventory (main).
Record the new inventory basis in `docs/fork/patches.md` (uzh/main `529d9c0`,
upstream `v1.2.0` `fd9a4fa`), the ci.yml overlap, and the unchanged
dispositions. Acceptance: ledger text matches the merged tree; no stale
claims.

S3 — Verification battery (main).
Run on the merged head: service `bun test`, api `bun test`, packages/code
`npm run build && node --test dist/*.test.js` (any failure compared against
pristine `v1.2.0`), workflow YAML parse, and the release-versioning scripts.
Helm and Dockerfile checks are skipped with reason (no chart/Dockerfile
change). Acceptance: all green at the exact head or inherited-only failures
proven byte-identical to pristine `v1.2.0`.

S4 — Reviews and draft PR (main + reviewers).
Simplifier scoped to fork-authored hunks (upstream-carried code stays
byte-identical for merge-sync), one slice review with the security and
architecture lenses on the merge, one integrated final review, then the
rs-mr-description-writer draft PR. Acceptance: review findings resolved or
recorded; draft PR open with verification receipts.

## Test portfolio

| Risk | Obligation | Seam | Failure it must catch |
| --- | --- | --- | --- |
| Merge silently drops a fork line | existing | fork-delta diff check | fork behavior lost in a file both sides touch |
| New root-access code weakens sandbox containment | upstream + CI step | root-access/native-sandbox tests | selected roots escape containment |
| Admission reporting misreports capacity | upstream + CI step | fleet.test.ts with isolated Redis | capacity errors surface as timeouts |
| Repository instructions read unbounded input | upstream | instructions tests | unbounded or unlisted file reads |
| Release guard lost in the merge | existing | release.yml byte-check | fork job guard or resolver diverges |

## Working context

- The primary checkout's `.git` is read-only; execution runs in the writable
clone `/tmp/ci-reconcile-1` (origin = uzh-bf fork over https, upstream =
LibreChat-AI). Push the task branch from there.
- Host toolchain: bun 1.3.14, node 24.17.0, docker 29.4.0; service and api
suites run on the host; packages/code uses its build plus node test runner.
- Rollback: ordinary source revert of the merge commit on the branch;
deployment rollback stays declarative through df-cloud/Helm (out of scope).

## Authority

Granted within this package: branch creation, merge work, commits, task-branch
push, draft PR, local test runs, read-only `gh` evidence. Standing
implementation delivery applies.

Separately gated (asked at the end, not executed): merge into `main`, whose
push will run CI plus the standing `Build CodeAPI Images` job that publishes
the seven `<sha>`/`main` GHCR images exactly as on PR #24/#25; closing
dependabot PRs #4/#14/#16 (all `CONFLICTING`; `main` already carries
`@opentelemetry/core` 2.8.0 and `nanoid ^5.1.16`, and `api` has no
`body-parser` dependency, so all three are superseded); PR #21 disposition
(draft, `CONFLICTING`, 1030/202 lines across `api/openapi.yaml`,
`service/openapi.yml`, and five service files; its
`service/src/openapi-contract.test.ts` is absent from `main`, so it needs
re-derivation rather than a blind rebase); deleting merged branches or
worktrees (`rs/fix-release-version-resolution` is merged into `main`);
image publication; any GitOps/deployment promotion.

## Progress

- 2026-09-18: PR #25 merged (`529d9c0`, merge commit) with the release-job
guard; post-merge CI and image build running; fork tags/releases still 0/0.
- 2026-09-18: trial merge of `v1.2.0` clean; overlap analysis and logging-sink
check done; this plan drafted.
- 2026-09-18: S1 merge `abff6b7` (true merge commit, upstream parent
`fd9a4fa`); resolver files byte-identical to `v1.2.0`, `release.yml`
differs only by the fork guard. S2 ledger `c5aee61`.
- 2026-09-18: S3 verification at `c5aee61`: service `bun run test` 1097 pass /
0 fail / 12 skip; api `bun run test` 481 pass / 0 fail; fleet admission with
isolated Redis 1 pass; packages/code 506 tests / 483 pass / 11 fail with the
failure set identical to pristine `v1.2.0` (environment-inherited macOS
ACL/Koffi class); workflow YAML parses; `release-version-resolution.sh` and
`release-versioning.sh` pass. Two initial runs were invalidated: a stale
container-installed `node_modules` in the clone produced 73 spurious
packages/code failures, and running three suites concurrently pushed the
240-input api test past its 30 s timeout; the clean reinstall and quiet-host
reruns reproduced the numbers above.
- 2026-09-18: S4 routes: slice review on `combo/glm-5.3-flash` (max) returned
DONE with no findings; it reproduced blob-identity for 27/28 merge files and
checked the security lenses (root containment, instruction reads, admission).
Simplifier: the native `gpt-6-astra` route is blocked by the account usage
limit (until 2026-09-20) and the Claude CLI fallback failed with an expired
OAuth token; per the continuity ladder the non-gate simplification pass
returned to the main session with no net-simplification changes identified in
the docs hunks. Final review: Claude CLI failed terminally and AGY is not
logged in, so the documented one-shot GLM final-review fallback carries the
complete final-review contract.
- 2026-09-18: final review (GLM 5.3 Flash continuity fallback with the complete
final-review contract) returned DONE with no findings; it reproduced the
range and merge topology, the 27/28 blob-identity, plan compliance, and the
security spot-checks. Recorded limitations: same model family as the slice
reviewer, verification battery accepted per contract, branch CI pending the
push. Local reports: docs/project/_local/reviews/2026-09-18-upstream-v1.2.0-integration-*.md.
- 2026-09-18: S4 closed. Draft PR #26 opened against `main` (never-squash
merge expected, matching PR #24). CI run `35341483663` at head `a25ea9a`
completed **success**: all ten checks green — Deployment Config, Launcher,
API, Service (including the new "Verify fleet admission with isolated
Redis" step), three Node code-package jobs, macOS Storage ACL, Lambda
MicroVM Provisioning, and the arm64 runner-image build. PR merge state
`CLEAN`/`MERGEABLE`, draft. The fork still has 0 tags / 0 releases, and a
branch push runs no image workflow.
- 2026-09-18: terminal condition met. No further work is authorized in this
package; every remaining action is a separately gated decision listed above.
57 changes: 57 additions & 0 deletions packages/code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,50 @@ chosen non-overlapping project directories with `--workspace` or `--environment`
Do not also register their parent directory. Treat the inventory as a snapshot;
normal workspace admission must validate any directory selected from it.

## Register selected projects

After pairing, use paths from `projects --root` to register individual checkouts:

```bash
librechat-code run --project-root /srv/projects \
--project web --project services/api \
--allow-workspace-writes --allow-workspace-commands
```

Only the explicitly listed checkouts become execution roots. The discovery
directory is not registered, and adding a new sibling repository does not grant
access to it. In LibreChat, select the project in the existing workspace picker;
the conversation stores that selection for subsequent tools and approval resumes.
An agent's default workspace and the user's recent selection work as before.

Project IDs are derived from the canonical discovery directory and relative
project path, not the branch or selection order. Keep both paths unchanged across
restarts to retain chat bindings. Moving a checkout changes its ID. These are
registration IDs, not the root-local IDs printed by the inventory command.

Up to 32 selected projects are supported. Each must be a standalone Git checkout;
linked worktrees, symlink traversal, overlapping roots, and duplicate selections
are rejected. Existing native sandbox, command/write permissions, lease-slot and
quarantine rules still apply. This mode cannot be combined with `--environment`,
`--worker-dir`, `--workspace`, default-workspace, or workspace ID/name settings.
Existing registrations are not migrated automatically; use a new conversation
when switching registration mode. Non-Git directories still use the existing
workspace flags. Named environment setup/actions still use `--environment`.

Selected projects require macOS or Linux (including WSL2). Each request opens
and verifies the admitted directory, then retains that descriptor through file
access, repository-instruction loading, command startup, and replay copying.
Renaming a project cannot redirect an in-flight request to a replacement checkout;
subsequent requests reject the changed identity. Restart with an explicitly
selected replacement to admit it. Descriptors close when requests settle, and
independent workspaces do not share a current directory or global execution lock.

This reuses the existing workspace protocol. Programmatic tool calling requires
a LibreChat version that preserves the selected workspace across initial
execution and replay, plus the worker's normal programmatic prerequisites.
Installation alone does not restart workers or change registration; update your
worker service arguments explicitly.

## Pair

Hardened deployments use a one-time code instead of copying a long-lived
Expand Down Expand Up @@ -648,6 +692,19 @@ librechat-code run \
--allow-workspace-commands
```

Slots are per machine, not a fleet-wide execution limit. A busy machine does not
consume another machine's slots. Requests for the same root remain serialized,
including commands started through background tools. Independent checkouts can
use different slots; selecting subdirectories beneath one registered parent root
does not create separate scheduling boundaries. Linked Git worktrees share Git
metadata and are not supported by selected-project registration.

Admission waits at most 30 seconds. A `WORKSPACE_QUEUE_TIMEOUT` response (HTTP
503, `Retry-After: 1`) means the operation was not assigned or started; wait for
capacity before submitting it again. This is distinct from `ASSIGNMENT_EXPIRED`
or a transport timeout after dispatch, where execution may have occurred and
mutations must not be blindly retried. No automatic retry is added by this policy.

Keep the existing URL, pairing/identity, and network policy configuration.
The primary root keeps its configured workspace ID (default `primary`). Repeat
`--workspace id=path` to add named roots, up to the protocol's 32-root limit.
Expand Down
Loading
Loading