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 JSON

page:docs-upstream-intake

Structured · live

Upstream intake: cherry-picking public fixes into fabric json

Inspect the normalized record payload exactly as the atlas UI reads it.

File · wiki/docs/upstream-intake.mdCluster · wiki
Record JSON
{
  "id": "page:docs-upstream-intake",
  "_kind": "Page",
  "_file": "wiki/docs/upstream-intake.md",
  "_cluster": "wiki",
  "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": "\n# Upstream intake: cherry-picking public fixes into fabric\n\nStatus: 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`.\n\n`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.\n\n## 1. The `upstream` remote is fetch-only\n\nEvery 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:\n\n```bash\ngit remote add upstream https://github.com/a5c-ai/babysitter.git\ngit remote set-url --push upstream no_push\ngit remote -v\n# origin    git@github.com:a5c-ai/fabric.git (fetch)\n# origin    git@github.com:a5c-ai/fabric.git (push)\n# upstream  https://github.com/a5c-ai/babysitter.git (fetch)\n# upstream  no_push (push)\n```\n\n`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.\n\nRules that follow from `docs/DIVERGENCE-POLICY.md` §1–2:\n\n- 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).\n- 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.\n- 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).\n\n## 2. When intake is allowed\n\nIntake 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:\n\n1. 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.\n2. 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\").\n3. 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.\n4. It is not already in fabric under another commit, and it has not been superseded on the public `main` by a later change.\n\nBulk 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.\n\nReview the candidates with read-only commands only:\n\n```bash\ngit fetch upstream --no-tags --prune\ngit log --oneline origin/main..upstream/main                      # public main ahead of fabric main\ngit log --oneline origin/staging..upstream/staging\ngit log --oneline --remotes=upstream --not --remotes=origin        # every public commit fabric lacks (all branches)\ngit show --stat <sha>\ngit diff <sha>^ <sha> | git apply --check                          # quick applicability probe (no 3-way; a failure is not final)\n```\n\n## 3. The cherry-pick flow\n\nOne upstream commit, or one tight series, per pull request. The branch name is `intake/<short-sha>` of the first (or only) upstream commit.\n\n```bash\ngit fetch upstream --no-tags --prune\ngit switch -c intake/<short-sha> <fabric base branch>     # main, staging, or the feature branch the fix belongs on\ngit cherry-pick -x <sha>                                  # -x records \"(cherry picked from commit <sha>)\" in the message\n# for a tight series, oldest first:\ngit cherry-pick -x <sha-1> <sha-2>\n```\n\n`-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.\n\nIf a file moved in fabric (see §5), use rename-aware cherry-picking, or apply the patch into the new directory:\n\n```bash\ngit cherry-pick -x -X find-renames <sha>\n# or, when the whole subtree moved:\ngit format-patch -1 --stdout <sha> | git apply -3 --directory=<new-dir> -p<N>\ngit commit -a -m \"<subject>\" -m \"(cherry picked from commit <sha>)\"\n```\n\nThen 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):\n\n```bash\nnode scripts/ci/public-push-guard.cjs --self-test\ngit push -u origin intake/<short-sha>\ngh pr create --base <fabric base branch> --label upstream-intake --template upstream-intake.md\n```\n\nNever 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).\n\n## 4. Pull request requirements\n\nEvery intake pull request:\n\n- 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`);\n- 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:\n  - the upstream SHA(s) in full, with subject, public branch, author and date;\n  - 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\";\n  - the path map: one row for every touched file, public path to fabric path, marked `identical`, `renamed (<old> -> <new>)` or `dropped` (§5);\n  - conflicts and dropped hunks, per hunk, with the reason (§6);\n  - test evidence: the commands run and their result;\n  - the checklist, including `git remote -v` showing `upstream ... no_push (push)`;\n- 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`);\n- passes CI, including the `public-push-guard` job.\n\nReviewers 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.\n\n## 5. Path map: public paths to fabric paths\n\nThe 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:\n\n| Public path or name | Fabric path or name | Since | Affects |\n|---|---|---|---|\n| `packages/sdk/` | `packages/babysitter-sdk/` | public commit `47fd0e280` (2026-06-06), shared history | public commits authored before that rename (older feature branches) |\n| `@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 |\n| 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`) |\n| 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 |\n\nAt 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.\n\n## 6. Conflict policy: fabric wins\n\nDivergence is licensed (D17: fabric is \"free to diverge in implementation\"). On a conflict:\n\n1. Keep fabric's version of the conflicting hunk. Do not restructure fabric's code to make the public patch apply cleanly.\n2. 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.\n3. Record every dropped hunk in the pull request (file, what upstream changed, what fabric keeps, why).\n4. 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).\n\nA public commit that was itself superseded on public `main` is treated as already-decided upstream and is not taken.\n\n## 7. What is forbidden\n\n| Action | Why | Enforced by |\n|---|---|---|\n| `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 |\n| `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) |\n| `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) |\n| `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) |\n| 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) |\n| `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 |\n| a submodule pointing at the public repository | a pushable checkout inside the tree | guard (`submodule-public` rule) |\n\nThe 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`.\n\n## 8. How the propagation watch treats intake pull requests\n\n`.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.\n\nConsequences for intake:\n\n- 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).\n- 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.\n- Open (unmerged) intake PRs do not count. The rehearsal PR below stays open until the owner merges it; the watch is unaffected either way.\n\n## 9. Rehearsal record (WP-RN-02, 2026-09-28)\n\nThe 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`.\n\nCandidate 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):\n\n| Candidate | Decision | Reason |\n|---|---|---|\n| `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 |\n| `02e3a8773` ci: remove the cluster deploy pipeline from the public publish workflows (`staging`) | rejected (§2 rule 3) | would delete fabric's deploy pipeline |\n| `64fd9f475` test(ci): pin publish workflows to have no cluster deploy jobs (`staging`) | rejected (§2 rule 3) | asserts the absence of jobs fabric has |\n| `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 |\n| `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 |\n| `58891e42a` docs: apply enforcement messaging (`docs/improve-readme-and-best-practices`) | rejected | reverted on its own branch (`b62f317ac`) |\n| `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 |\n\nPath 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.\n\nPull 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.\n\n## 10. Naming rules for any unit that enters fabric (spec 15 §3.3, WP-RN-08)\n\nThese 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.\n\n1. 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\").\n2. 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.\n3. 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.\n4. 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.\n\nEnforcement: `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`.\n",
    "documents": []
  },
  "outgoingEdges": [],
  "incomingEdges": [
    {
      "from": "page:docs",
      "to": "page:docs-upstream-intake",
      "kind": "contains_page"
    }
  ]
}

Shortcuts

Back to overview
Open graph tab