Repository navigation
Lessons from moving the Go SDK out of core (preliminary migration playbook) #5273
rhuss
started this conversation in
Design Discussion
Replies: 2 comments
Update after the first lockstep release (core and SDK v0.1.8)The automation phase is done, and the retirement PR is open (#5461). What we learned since the first post:
Timeline on release day: core v0.1.8 at 18:14 UTC, SDK v0.1.8 tagged at 18:42 UTC, with two fixes (Go toolchain, README line) merged in between. |
0 replies
|
I updated the post above to the final playbook: phases 3 to 5 are filled in from the run, each phase ends with how it went, and the release-day lessons from my previous comment are part of it. |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The Go SDK move is complete. ai-openshell/sdk-go carries the history and builds on its own, core and SDK v0.1.8 shipped as the first lockstep release on 2026-11-10 (the SDK tag 28 minutes after core's), and #5461 removed
sdk/gofrom core on 2026-11-11. It was the first of the RFC 0019 moves (#4426), so here is what we learned, as a checklist that the next moves (the Python SDK is already under way, then the TypeScript SDK,packages, andwindows) can copy.This replaces the preliminary version from 2026-11-04. Phases 3 to 5 (automation, retirement, first lockstep release) are no longer pending, each phase ends with how it went, and the lessons from release day are in. RFC 0019 hasn't merged yet, so the playbook stays here for now; once it does, I'll propose it as
rfc/0019-repository-migration/playbook.md.Feedback I'd find most useful:
Next is a
migrate-repoagent skill that walks these phases as gated stages, with the history, verification, and porting scripts bundled. The move itself was driven with intent-driven development (cc-spex and spec-kit), and the playbook is meant to be fed to your agents as much as read.Tracking issue for the Go move: #5031.
Who this is for
Maintainers planning one of the remaining RFC 0019 moves: the Python and TypeScript SDKs,
packages,windows, and later the provider repositories. Every move leaves the same core repository, so the lessons about core's PR gates apply to all of them. Placeholders:<component>(for example "Python SDK"),<subdir>(its path in core),<target>(the newai-openshell/...repository),<surface>(the name core's prompts and scripts use for the component, for examplego-sdk).Phases
Each phase lists its entry gate and a checklist you can copy into the tracking issue. The Go move took six calendar days from the first issue to the core cutover and thirteen to the removal from core, most of it waiting for approvals and for the next core release.
<target>mainstate:acceptedon the core issue<subdir>, open PRs ported<subdir>removed from core<target>Phase 0: Prerequisites
state:acceptedbefore any core PR.main-integrity: PR, approval, code owner, last-push approval, no force push) and your access to<target>andai-openshell/infra(gh api repos/<org>/<repo> --jq .permissions).tasks/*.tomlaggregates, CodeQL matrix and config, release workflows, Dependabot, CODEOWNERS, review prompts and their validators. Search for the path and for<surface>.<subdir>. Sort them into component-only PRs, core features with hand-written component changes, and PRs that only regenerate bindings./ok to test <sha>), maintainer approval, and open review threads.Phase 1: Import
hack/migration/FREEZE).git filter-repofrom a throwaway clone reduced to one branch at the freeze commit. Rewrite#NtoNVIDIA/OpenShell#N. Run withGIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null.<target>with--allow-unrelated-historiesand a merge commit. Resolve the auto-init README conflict in favor of the component's README.main, build the README example).Phase 2: Cutover and porting
<subdir>, and add a required check that fails on added or modified files there. Exempt deletions and the notice files instead of relying on a label./ok to test. After the CI mirror runs, answer review comments without pushing and carry polish into the next PR.format-patch --relative=<subdir> --no-signoffandgit am. Rewrite renamed paths inside the patches before applying, and only in lines the port adds. Port only the top PR of a stack.<target>, rebase every stacked branch right away. Verify each push withgit ls-remoteand read lease SHAs from it.Phase 3: Automation
gh api orgs/<org>/teams; every team named needs repository access), Dependabot, CodeQL, workflow linting (actionlint, zizmor, shellcheck), docs publishing, CONTRIBUTING, SECURITY, AGENTS. Follow org-wide choices (the DCO GitHub app) over copies from core.mainbefore the first automated PR arrives. Required DCO alone let a failing dependency update merge.maincan deploy to.<target>and anything consumers must do.How it went: the first live watcher run opened a bot PR with CI and E2E on it. Over 140 hourly runs proposed every pre-release once, with no duplicates. The nightly drift check stayed quiet against core
mainand keeps a single issue. Bot steps that need PR context (an agent triggered by a label) can't reach secrets limited tomain, so they need their own design (pull_request_targetrestricted to the bot's branches is one option).Phase 4: Retirement
<subdir>, its tasks and toolchain, CodeQL entries, release jobs and theirneedsand expected-job checks, and the freeze check. Rewrite the user docs page for the new location, with examples compiled against the new package.sync-agent-infraskill and search for<surface>as well as the path. Check that the removed jobs are not required status contexts.How it went: the Go module proxy and pkg.go.dev showed the deprecation as soon as the release created
sdk/go/v0.1.8, andgo getprints it. Core's docs page now describes the new package and keeps the migration steps from the old one.Phase 5: Release
<target>'smainis green: the stable proposal opens minutes after the core release and inherits whatever is red.How it went: core v0.1.8 was released at 18:14 UTC, and SDK v0.1.8 was tagged at 18:42 UTC. Two fixes landed in between: the Go toolchain, after a dependency update had raised the minimum, and a README version line that the stable proposal hadn't updated after a merged pre-release proposal.
Lessons by topic
Governance
ai-openshellappliesmain-integrityto every Terraform-managed repo, and only org admins can bypass.require_last_push_approvalplus a team without a second reviewer means nothing can merge without an admin. Grow the owning team before the move.maintainers, notopenshell-maintainers).DCOfile.ai-openshell/infra. Plan an infra change (made by an infra team member) as step zero.state:acceptedissue for every core-side PR. The tracking issue must stay open, so file one issue per core PR.Automation identity
GITHUB_TOKENdo not trigger workflows. Bot PRs need a GitHub App token.workflows: write.GITHUB_TOKENoverrides theghkeyring login. Checkgh auth statuswhen a push of workflow files fails with a missingworkflowscope.CI coupling
Releases
sdk/go/vX.Y.Z) can break tooling that runsgit describe(setuptools-scm in fix(ci): keep Release Dev publishing when the snap upload or a Go tag breaks it #5018). Separate repos remove that class of problem.gh apiputs 404 error JSON on stdout.mainbefore core's release day; the stable proposal inherits whatever is red.golang.org/xmodules follow the two supported Go releases). The toolchain pin, and the consumers' minimum, move with them.History
sdk/go). Filtered history keeps them, which is acceptable in exchange for blame and authorship.#Nreferences toNVIDIA/OpenShell#Nduring extraction, or they autolink to the new repo's issues.git filter-repocrashes on multi-line alias values ingit config --list. Run it withGIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null.Deprecation
Porting
/ok to testis pinned to a SHA. Every push by the author needs a new one, so a PR fixed after review silently waits again.pull_requestworkflows as "awaiting approval" until a maintainer clicks "Approve and run". They are not part of Required CI Gates./ok to testlands, don't push non-blocking polish. Answer the review and carry the polish into the next PR.format-patch --relative=<subdir>plusgit am, and rewrite renamed paths inside the patches before applying.--no-signofftoformat-patch; a porter'sformat.signoff=trueadds their sign-off to every contributor's commit.amresolution with--theirsstill has old paths. Rewrite the resolved lines beforegit am --continue.git ls-remote, not the push output, and read lease SHAs from it too.Docs
All reactions