Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · Upstream intake: cherry-picking public fixes into fabric
page:docs-upstream-intakea5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
II.
Page overview

page:docs-upstream-intake

Reference · live

Upstream intake: cherry-picking public fixes into fabric overview

Inspect the raw attributes, linked wiki pages, and inbound or outbound graph edges for page:docs-upstream-intake.

PageOutgoing · 0Incoming · 1

Attributes

nodeKind
Page
sourcePath
docs/UPSTREAM-INTAKE.md
sourceKind
repo-docs
title
Upstream intake: cherry-picking public fixes into fabric
displayName
Upstream intake: cherry-picking public fixes into fabric
slug
docs/upstream-intake
articlePath
wiki/docs/UPSTREAM-INTAKE.md
article
# Upstream intake: cherry-picking public fixes into fabric Status: binding. Implements `docs/specs/platform-gaps/15-private-isolation-rename.md` §1.4 (cherry-pick-only intake) and §1.5 (divergence policy) under decision D17 of `docs/specs/platform-gaps/00-intent.md`; executed by WP-RN-02. The policy this procedure serves is `docs/DIVERGENCE-POLICY.md`; the cutover record is `docs/specs/platform-gaps/phase0/watch-baseline.md`; the rehearsal of this procedure is `docs/specs/platform-gaps/phase0/intake-rehearsal.md`. `a5c-ai/fabric` is the private product repository. The public `a5c-ai/babysitter` repository is a separate, open project that this repository reads from and never writes to. Public fixes reach fabric in exactly one way: a maintainer cherry-picks individual public commits onto a fabric branch and lands them through a pull request labeled `upstream-intake`. There is no other path: no merges, no pulls, no shared tags, no automation. ## 1. The `upstream` remote is fetch-only Every clone that takes part in intake configures the public repository as a remote named `upstream` whose push URL is disabled. Run these exact commands once per clone: ```bash git remote add upstream https://github.com/a5c-ai/babysitter.git git remote set-url --push upstream no_push git remote -v # origin git@github.com:a5c-ai/fabric.git (fetch) # origin git@github.com:a5c-ai/fabric.git (push) # upstream https://github.com/a5c-ai/babysitter.git (fetch) # upstream no_push (push) ``` `no_push` is not a URL, so `git push upstream ...` fails mechanically before contacting GitHub. The propagation watch (`scripts/ci/upstream-propagation-watch.sh`) refuses to run unless the push URL is exactly `no_push`, and the CI guard (§7) fails any workflow or script that configures the public repository as a remote without it. Rules that follow from `docs/DIVERGENCE-POLICY.md` §1–2: - No clone of fabric may carry a pushable remote for `a5c-ai/babysitter` under any name; `git clone` of the public repository into a fabric working tree is not done (fetch it through `upstream` instead). - Never `git push upstream`, never `git push <public-url>`, never `gh pr create -R a5c-ai/babysitter`, never a `gh api` write (`POST`/`PUT`/`PATCH`/`DELETE`) against `repos/a5c-ai/babysitter`. Read-only access (`git fetch`, `git ls-remote`, `gh api` `GET`, `gh pr list -R a5c-ai/babysitter`) is the only permitted interaction. - Never fetch the public tags: always `git fetch upstream --no-tags`. Public `babysitter/<branch>/v*` tags must not enter fabric's tag namespace (fabric's release tags are `fabric/<branch>/v*`, WP-RN-07). ## 2. When intake is allowed Intake is pull-based and opportunistic (spec 15 §1.4). It is done by a maintainer at their own cadence, never on a schedule and never by automation. A public commit is a candidate when all of the following hold: 1. It is a fix or a self-contained addition fabric actually wants: security fixes to the journal, replay and trust cluster first (spec 15 §1.5: evaluated in the intake owner's next review pass), then bug fixes, then documentation or data records. Features are taken only when fabric has decided to adopt them. 2. It is small enough to review as a unit: one commit, or one tight series of commits that only makes sense together (for example "create record" + "amend record"). 3. It does not contradict fabric's divergence. A public commit that describes the public project's own arrangements (for example, that deployment happens "elsewhere") is not taken into the repository it would misdescribe. 4. It is not already in fabric under another commit, and it has not been superseded on the public `main` by a later change. Bulk intake, if ever wanted, is scheduled before WP-RN-10 executes the directory renames (spec 15 §1.4 binding sequencing rule); afterwards intake is expected to shrink to targeted fixes. Review the candidates with read-only commands only: ```bash git fetch upstream --no-tags --prune git log --oneline origin/main..upstream/main # public main ahead of fabric main git log --oneline origin/staging..upstream/staging git log --oneline --remotes=upstream --not --remotes=origin # every public commit fabric lacks (all branches) git show --stat <sha> git diff <sha>^ <sha> | git apply --check # quick applicability probe (no 3-way; a failure is not final) ``` ## 3. The cherry-pick flow One upstream commit, or one tight series, per pull request. The branch name is `intake/<short-sha>` of the first (or only) upstream commit. ```bash git fetch upstream --no-tags --prune git switch -c intake/<short-sha> <fabric base branch> # main, staging, or the feature branch the fix belongs on git cherry-pick -x <sha> # -x records "(cherry picked from commit <sha>)" in the message # for a tight series, oldest first: git cherry-pick -x <sha-1> <sha-2> ``` `-x` is mandatory: the recorded upstream SHA is what reviewers, the propagation watch and future audits use to trace the commit to its public origin. If a file moved in fabric (see §5), use rename-aware cherry-picking, or apply the patch into the new directory: ```bash git cherry-pick -x -X find-renames <sha> # or, when the whole subtree moved: git format-patch -1 --stdout <sha> | git apply -3 --directory=<new-dir> -p<N> git commit -a -m "<subject>" -m "(cherry picked from commit <sha>)" ``` Then run the checks that are directly relevant to the touched files (the package's own test suite, the docs gates for documentation, the guard for anything under `.github/` or `scripts/`), push the branch to `origin` only, and open the pull request (§4): ```bash node scripts/ci/public-push-guard.cjs --self-test git push -u origin intake/<short-sha> gh pr create --base <fabric base branch> --label upstream-intake --template upstream-intake.md ``` Never rebase an intake branch onto a public head, never `git merge upstream/<branch>`, never `git pull upstream <branch>`: the branch is built from fabric's history plus the cherry-picked commits and nothing else (`docs/DIVERGENCE-POLICY.md` §3). ## 4. Pull request requirements Every intake pull request: - targets a fabric branch and carries the label `upstream-intake` (`gh label create upstream-intake --description "Cherry-picked from public a5c-ai/babysitter" --color 0E8A16`, already present on `a5c-ai/fabric`); - uses the template `.github/PULL_REQUEST_TEMPLATE/upstream-intake.md` (`gh pr create --template upstream-intake.md`, or open the PR on GitHub with `?template=upstream-intake.md`) and fills in every section: - the upstream SHA(s) in full, with subject, public branch, author and date; - the upstream pull request or issue link when one exists (`gh pr list -R a5c-ai/babysitter --search <sha>` is a read-only lookup), or "none"; - the path map: one row for every touched file, public path to fabric path, marked `identical`, `renamed (<old> -> <new>)` or `dropped` (§5); - conflicts and dropped hunks, per hunk, with the reason (§6); - test evidence: the commands run and their result; - the checklist, including `git remote -v` showing `upstream ... no_push (push)`; - contains only the listed upstream commits (plus, if unavoidable, one fabric-authored fix-up commit for name or path adaptation, clearly titled `intake: adapt <file> to fabric layout`); - passes CI, including the `public-push-guard` job. Reviewers verify that the commit message carries the `(cherry picked from commit <sha>)` trailer, that the SHA exists on the public repository (`git branch -r --contains <sha>` after `git fetch upstream --no-tags`), and that the path map covers every file in the diff. ## 5. Path map: public paths to fabric paths The path map is required even when every path is identical, because the two trees diverge over time and the map is the record of what was checked. Known differences between the public layout and fabric's, to be extended as the rename work packages land: | Public path or name | Fabric path or name | Since | Affects | |---|---|---|---| | `packages/sdk/` | `packages/babysitter-sdk/` | public commit `47fd0e280` (2026-06-06), shared history | public commits authored before that rename (older feature branches) | | `@a5c-ai/<package>` npm names | `@fabricstack/<name>` per spec 15 §3.1 | WP-RN-05 (not yet executed) | any commit touching `package.json` names or import specifiers, once RN-5 lands | | package directories | spec 15 §3.3 directory matrix | WP-RN-10 (not yet executed) | every intake, once RN-10 lands (`git apply --directory` or `-X find-renames`) | | public release tags `babysitter/<branch>/v*` | never imported; fabric tags are `fabric/<branch>/v*` | WP-RN-01 / WP-RN-07 | tag references in scripts and docs | At the time of the WP-RN-02 rehearsal, `git ls-tree` of `packages/` at `upstream/main` and at fabric's work branch showed no path differences (the trees share history up to the cutover baseline of 2026-09-28), so a current public commit maps 1:1 unless it was authored before a public rename. ## 6. Conflict policy: fabric wins Divergence is licensed (D17: fabric is "free to diverge in implementation"). On a conflict: 1. Keep fabric's version of the conflicting hunk. Do not restructure fabric's code to make the public patch apply cleanly. 2. Re-apply only the intended delta of the upstream commit on top of fabric's version, when that delta still makes sense in fabric's code. If fabric already solved the same problem differently, the upstream hunk is dropped, not merged. 3. Record every dropped hunk in the pull request (file, what upstream changed, what fabric keeps, why). 4. If nothing of the commit survives, do not open the pull request; record the evaluation instead (as the rehearsal record below does for the candidates it rejected). A public commit that was itself superseded on public `main` is treated as already-decided upstream and is not taken. ## 7. What is forbidden | Action | Why | Enforced by | |---|---|---| | `git merge upstream/<branch>`, `git pull upstream <branch>`, fast-forwarding onto a public commit, scheduled or automated merges | wholesale merges re-create the mirror relationship the split ended (`docs/DIVERGENCE-POLICY.md` §3) | propagation watch (unexplained public commits fail the audit); reviewer check of the PR's commit list | | `git push upstream ...`, `git push <public-url> ...`, `git remote set-url --push upstream <url>`, any remote for the public repository without `no_push` | invariant 1: nothing in fabric alters the public repository | `no_push` URL; `scripts/ci/public-push-guard.cjs` (`push-to-public`, `pushable-remote`, `push-url-set`, `ssh-url` rules) | | `gh pr create -R a5c-ai/babysitter`, `gh release create -R a5c-ai/babysitter`, `gh api -X POST/PUT/PATCH/DELETE repos/a5c-ai/babysitter/...`, `gh workflow run -R a5c-ai/babysitter` | same invariant | guard (`gh-write` rule) | | `actions/checkout` of `a5c-ai/babysitter` with a token, an ssh-key, `persist-credentials: true` or `contents: write` | a pushable working copy of the public repository inside CI | guard (`checkout-with-write` rule) | | any action step or agent dispatch pointed at `a5c-ai/babysitter` (`repository:` / `repo:` inputs) | fabric's automation acts on fabric only | guard (`action-targets-public` rule) | | `git fetch upstream` without `--no-tags`, `git fetch --tags upstream` | public tags must not enter fabric's tag namespace | `--no-tags` in every documented command and in the watch workflow | | a submodule pointing at the public repository | a pushable checkout inside the tree | guard (`submodule-public` rule) | The guard allows, by rule: `uses: a5c-ai/babysitter/<path>@<ref>` action references, `git fetch` and `git ls-remote`, `gh api` `GET` calls and `gh ... list/view` commands, the fetch-only remote idiom, npm package names under `@a5c-ai/`, comments and Markdown, and a line annotated `# public-push-guard: allow <reason>` (the reason is mandatory and is reviewed like any other change). Run it locally with `node scripts/ci/public-push-guard.cjs` (`--self-test` also proves the negative fixtures in `scripts/ci/fixtures/public-push-guard/` trip); unit tests: `npm run test:public-push-guard`. ## 8. How the propagation watch treats intake pull requests `.github/workflows/upstream-propagation-watch.yml` fetches the public heads daily over the fetch-only remote and computes the public commits that post-date the cutover baseline. For every such commit reachable from a fabric ref it looks for a **merged** pull request on `a5c-ai/fabric` labeled `upstream-intake` whose merge commit contains that public commit (`gh pr list --state merged --label upstream-intake`). Found: the commit is reported as `OK ... arrived via upstream-intake PR #<n>`. Not found: the run fails with the commit and the fabric refs that contain it. Consequences for intake: - The label is load-bearing. A cherry-pick merged without the label is reported as an unexplained propagation until the label is added to the merged PR (the watch re-evaluates on its next run). - The cherry-picked commit has a new SHA, so it is never itself a "post-baseline public commit"; what the watch excuses is a public commit that reaches fabric with its original SHA, which only a merge or a push of public history can cause. Cherry-picks therefore never trip the watch; the label mainly documents provenance and covers the `-x` trailer lookup in audits. - Open (unmerged) intake PRs do not count. The rehearsal PR below stays open until the owner merges it; the watch is unaffected either way. ## 9. Rehearsal record (WP-RN-02, 2026-09-28) The procedure above was rehearsed once, end to end, on branch `intake/76434c2` off `phase0/hard-split-registry-guards`. Full record with commands and outputs: `docs/specs/platform-gaps/phase0/intake-rehearsal.md`. Candidate review (`git log --oneline --remotes=upstream --not --remotes=origin` listed 469 public commits fabric lacks; public `main` and `develop` had nothing beyond fabric; public `staging` had three): | Candidate | Decision | Reason | |---|---|---| | `d98b7ff70` docs: deployment is handled from a private deployment repository (`staging`) | rejected (§2 rule 3) | every hunk states that deployment happens outside the repository; fabric is that deployment repository | | `02e3a8773` ci: remove the cluster deploy pipeline from the public publish workflows (`staging`) | rejected (§2 rule 3) | would delete fabric's deploy pipeline | | `64fd9f475` test(ci): pin publish workflows to have no cluster deploy jobs (`staging`) | rejected (§2 rule 3) | asserts the absence of jobs fabric has | | `d5c7e7f77` fix(sdk): avoid non-portable fallback sdk symlinks (`agent/issue-1757`) | rejected (§2 rule 4, §6) | superseded on public `main` by `ded587848` (relative symlink targets, 2026-08-14), which fabric already has; the 3-way cherry-pick conflicted in `runSupport.ts` and `validation.ts` exactly on that hunk; fabric wins left nothing | | `442e7ed6a` feat(sdk): expose runId, runDir, artifactsDir on ProcessContext (`feat/expose-runid-...`) | rejected (§2 rule 4) | already present in fabric (`packages/babysitter-sdk/src/runtime/types.ts`); the commit predates the public `packages/sdk` -> `packages/babysitter-sdk` rename | | `58891e42a` docs: apply enforcement messaging (`docs/improve-readme-and-best-practices`) | rejected | reverted on its own branch (`b62f317ac`) | | `76434c235` Add upstream agent versions for 2026-07-15 (`agent-versions/daily-2026-07-15`) | **taken** | one commit, one new file `packages/atlas/graph/agent-stack/agent-versions/upstream-current-2026-07-15.yaml`, same shape as the 07-14 and 07-17 records fabric has; fills a gap in fabric's own catalog data | Path map of the taken commit: `packages/atlas/graph/agent-stack/agent-versions/upstream-current-2026-07-15.yaml` -> identical path in fabric (new file). Conflicts: none. Sibling commits `96ad4691b` (evidence sources for the same day) and `12eafcc00` (Cursor and Hermes records) are the natural follow-up tight series and were left for a second intake so the rehearsal stays at one commit. Pull request: <https://github.com/a5c-ai/fabric/pull/2> (base `phase0/hard-split-registry-guards`, head `intake/76434c2`, fabric commit `d39bba75d`, label `upstream-intake`). The public origin of the commit is a5c-ai/babysitter pull request #1422 (looked up read-only with `gh pr list -R a5c-ai/babysitter --head agent-versions/daily-2026-07-15 --state all`). The PR was opened, not merged, by WP-RN-02: merging is the owner's decision. ## 10. Naming rules for any unit that enters fabric (spec 15 §3.3, WP-RN-08) These rules apply to every pull request that adds or moves a `package.json`, whichever way the code arrives: a public-babysitter cherry-pick (this document), a t3code fork or extraction (`docs/specs/platform-gaps/10-t3code-migration.md`, WP-T3-01 and later), or fabric-authored work. 1. A unit migrated from t3code is born under its spec 15 §3.3 name and directory — `@fabricstack/contracts` at `packages/contracts`, `@fabricstack/acp` at `packages/acp`, `@fabricstack/codex-protocol` at `packages/codex-protocol`, `@fabricstack/ssh` at `packages/ssh`, `@fabricstack/tailscale` at `packages/tailscale`, `@fabricstack/environment` at `apps/environment` (bin `environment-server`), `@fabricstack/client-runtime` at `packages/client-runtime`, `@fabricstack/console-web` at `apps/console-web`, `@fabricstack/console-desktop` at `apps/console-desktop`, `@fabricstack/relay` at `infra/relay` — with `publishConfig.registry` pinned to the Artifact Registry URL (spec 15 §4.3 G1). There is no interim name and no interim directory, not even for one commit (spec 15 interaction rule 1: "no double rename"). 2. A new unit never carries `@t3code/*`, `t3-*`, one of t3code's own names (`@t3tools/*`, `t3`, `t3code-*`, `effect-acp`, `effect-codex-app-server`), `@a5c-ai/*`, a scope spec 15 §2 rejected, or no scope at all. Upstream names belong in `UPSTREAM.json`, `LICENSE-THIRD-PARTY` and provenance headers only. 3. A `@fabricstack/*` name must be one the spec lists (§3.1/§3.2 new-name column or §3.3 table); a spec target directory holds exactly the package the spec assigns to it. Existing `@a5c-ai/*` units keep their current names until WP-RN-05 renames them — moving one to its new directory while keeping its old name is the double rename the gate exists to stop. 4. The only exemption is the spec 15 §3.2 retirement list (the eight `genty` device/web/desktop shells deleted by T-27), which is never renamed. Enforcement: `node scripts/ci/no-double-rename.cjs` (CI job `publish-isolation`; `--self-test` proves the negative fixtures under `scripts/ci/fixtures/no-double-rename/` trip) scans every workspace manifest and every `package.json` under `packages/`, `apps/` and `infra/`, treats any name absent from `scripts/ci/fixtures/no-double-rename/baseline-packages.json` as a new unit, and fails the job with a `file:line` finding. It has no waiver annotation. Spec 10 itself is held to the same names by `node scripts/ci/check-spec10-names.cjs`. Record the outcome in the pull request's "Naming rules" table and checklist (`.github/PULL_REQUEST_TEMPLATE/upstream-intake.md`); the record of the gate's introduction is `docs/specs/platform-gaps/phase0/no-double-rename.md`.
documents
[]

Outgoing edges

None.

Incoming edges

contains_page1
  • page:docs·PageBabysitter Docs

Related pages

No related wiki pages for this record.

Shortcuts

Open in graph
Browse node kind