Skip to content

feat: clone Workspaces from Git Server snapshots and deliver Revisions over Git (internal Git line) - #81

Merged
EricWvi merged 28 commits into
ora-space:mainfrom
ObsisMc:feat/183-internal-git-line
Oct 21, 2026
Merged

EricWvi merged 28 commits into
ora-space:mainfrom
ObsisMc:feat/183-internal-git-line

Conversation

@ObsisMc

@ObsisMc ObsisMc commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Implements the Cloud side of the internal Git line (Git Server ⇄ Node) of Ora's Git-native Project code: the clone step consumes the Binding's current snapshot, Git Server grants follow the execution kind, Revisions are delivered and resumed over Git, and tenant-level clones are retired. Bundles and the download grant are removed.

Refs ora-space/circus#183

ADR status — approved

This PR implements ADRs that are approved (ora-space/specs#111 merged), not yet implemented:

  • decisions/cloud/operation/20261016-clone-step-consumes-binding-snapshot.md
  • decisions/cloud/controller-integration/20261016-snapshot-clone-input-and-execution-ref-grants.md
  • decisions/cloud/revision/20261017-git-native-delivery-refs-and-resume.md (supersedes the 20261012 Git Server delivery ADRs)

The owner-review changes made to those ADRs before approval are implemented in commits 13–16 below. A landing run (the third of the task's three runs) opens the specs PR that moves the three ADRs to implemented before this PR merges, and that specs PR merges after it; it updates the evidence of their core test cases (test-cases/cloud/controller-integration/snapshot-clone-input-and-execution-grants.md, test-cases/cloud/operation/clone-step-consumes-binding-snapshot.md, test-cases/cloud/revision/git-native-delivery-refs-and-resume.md). The documents in docs/ describe the code's behavior and state that the governing ADRs are approved.

Lands together with

The desktop and cluster PRs of the same line and specs#111: the internal control contract, the Controller and the Node change in one breaking switch. Desktop pins third_party/cloud to the contract commits below and must re-pin to the merged commit after this PR merges.

  • Contract commits: cfd7966 (feat(proto): clone from Git Server snapshots and deliver Revisions over Git), 0b6a15d (feat(proto): expose frozen snapshot clone inputs on operations), and a51ee11 (feat(proto)!: reserve the retired BUNDLE_FAILED revision failure reason), the latest contract commit desktop pins. The contract content is unchanged from before the rebase apart from merging with main's RecordProvisioningFact additions to operations.proto.
  • proto/buf.yaml keeps a one-time ignore_only exemption for the deleted v1 fields, messages, RPCs and enum values (CLONE_FAILURE_REASON_BRANCH_NOT_FOUND, REVISION_FAILURE_REASON_BUNDLE_FAILED, both now reserved); it is removed in the next change to that file.

Migrations

0053_retire_tenant_level_clones.sql and 0054_git_delivery_refs.sql, after the latest migration on main at the last merge, 0052_legacy_workflow_issue_run_settlement.sql. They were added as 0039/0040 (commits 6, 7) and renumbered after each merge of main (commit 12: 0043/0044; commit 17: 0044/0045; commit 22: 0045/0046; commit 25: 0046/0047; commit 26: 0050/0051; commit 27: 0052/0053; commit 28: 0053/0054). The upgrade test is TestMigration0053RetiresTenantLevelClonesKeepingWorkspaceClones (baseline: everything before 0053, including main's 0043–0052); TestRevisionShapeKeepsGitAndBundleRowsApart covers 0054's constraints. This branch's migrations touch tables no migration on main touches (0053: clone_requests, clone_executions, clone_event_receipts; 0054: revisions), and every upgrade test runs the later migrations on top of the earlier ones. All are listed in internal/core/migrations/README(.en).md.

Commits

  1. feat(proto): CloneSpec{repository_url, snapshot_ref, base_commit, workspace_ref}, PriorRevision and DeliverRevisionSpec with Git locations, AgentSessionSpec.workspace_directory, PUSH_REJECTED/PUSH_FAILED, GrantRevisionDownload/DownloadGrant deleted.
  2. feat(proto): OperationSnapshot.clone_input; OperationProject keeps only id. (Commits 1–2 do not compile alone; the codec follows in 3.)
  3. feat(controlgrpc): wire codec for the new shapes, the simulator's Git Server double, integration fixture on the double.
  4. feat(config): git_server settings, internal/gitrefquery, server wiring, gitServer in /healthz.
  5. feat(core): clone from the Binding's current snapshot (frozen input, park/fail without a snapshot, base_ref_not_synced, base_commit_mismatch, delete_project waits for repository Operations). Parking a run Workspace creation as blocked freezes its abandonment deadline in the same transaction, like a Controller deferral (TestBlockedCloneParkFreezesDeadlineInClaimTransaction).
  6. refactor!: retire tenant-level clones (migration 0039, /tenants/{tid}/clones, OpenAPI, frontend page, clone registry).
  7. feat(core): deliver and resume Revisions over Git (migration 0040, ref-query verification, resume from the prior's delivery ref).
  8. feat(core): Git Server grants by execution kind (clone read-only during its step, sessions write their own Workspace branches, deliveries create their delivery ref and fast-forward workspaceRef).
  9. feat(core): Workspace directory in the session input.
  10. docs: Git-native Workspaces and Revision delivery.
  11. test(revision): keep the Git Server across simulator restarts.
  12. Merge of main: renumbers the two migrations to 0043/0044; the work claim keeps main's claimed_run_id projection for workflow work and drops the retired tenant clone request branch; the public request no longer carries CloneID. After the merge task check (lint, format, full PostgreSQL suite), the full suite under -race, task build and task frontend:check pass, with no proto, OpenAPI or frontend client drift.

After ADR approval (specs#111)

  1. a51ee11 feat(proto)!: REVISION_FAILURE_REASON_BUNDLE_FAILED = 4 removed and both the value and name reserved, matching executions.proto's BRANCH_NOT_FOUND; buf.yaml's ENUM_VALUE_NO_DELETE exemption adds agent_executions.proto. A Node that still sends 4 is refused as INVALID_INPUT with nothing recorded (TestNodeMayNotReportTheReservedBundleFailure). task proto:check and buf breaking against upstream/main pass.
  2. 7c1c5ab fix(core): the session's workspaceDirectory leaves out WorkflowRun Workspaces (controller-integration D7). TestGitServerDeniesAWorkflowRunSession pins at the real Git Server that a WorkflowRun's agent_session gets 403 for reads and pushes (D5); the grant query already joined only IssueRuns.
  3. f388862 fix(core): a clone step that fails on the Binding's sync records only syncOperationId (operation D2); a run's preparation.syncErrorCode reads that sync's own error_code from repository_operations (falling back to the Binding's latest failed sync only when no ID was recorded). OperationResult.syncErrorCode is dropped from OpenAPI and the generated client.
  4. fd1936b docs: the three ADRs are approved; the proposed / under-review wording is gone (both languages).

Merge of the external Git line

  1. b9f569f Merge of main with the external Git line (cloud#76) and the shared egress policy. Both lines are kept: git_server.* (snapshot clone inputs, Revision delivery verification) and repository.* (repo-executor, Credential Store, sync and publish) configuration coexist. Where they met: a credentialed Project's Workspace clones its snapshot with no credential (operation D1), so the external line's requireRepositoryAccess guard, which no remaining caller used, is removed; Project creation takes the external line's HTTPS-only repository URL validation; publishing a Revision by revisionId uses the Revision's verified delivery_ref instead of the Node-local revision_ref (publish ADR, revision ADR D4), covered by TestPublishingARevisionUsesItsVerifiedDeliveryRef; git-server-preset completes a Project's own unfinished sync with the external line's operation shape. No proto change comes from main; the OpenAPI document and frontend client are regenerated.
  2. afd6b00 Merge of main (no conflicts).
  3. 1668ab5 test(integration): the internal line's fixture settles each new Project's first sync from its source repository, so a Project is active only once its snapshot exists. The external line's sync and publish tests that need an active Project now race for a sync a member asked for; the delete-waits publish case gives the Binding the credential a publish names.
  4. 72cfac1 docs(repository): publish only confirms that the source ref exists.

Second review round

  1. 4b772e6 Merge of main at 7cf4cda (feat(core): evaluate conditions with desktop's semantics #92–fix(api): 补回执行器槽位路径参数绑定 #94, fix: 提前校验开发登录并验证 Gateway 认证授权边界 #56). router.go keeps this branch's public request without CloneID, with SlotName as on main. fix(api): 补回执行器槽位路径参数绑定 #94 fixed the same dropped :slot binding this branch had restored, so this branch's duplicate integration/executor_slot_route_test.go is deleted and main's TestExecutorSlotMappingHTTPBindsSlotPath is kept. Both 0044 upgrade tests are kept in integration/migration_upgrade_path_test.go, and the migrations README keeps main's 0044 section before this branch's.
  2. e721cc0 fix(migrations): renumber this branch's migrations to 0045/0046 after main's 0044 (file names, upgrade test name and baseline, internal/core/migrations/README(.en).md, docs/runtime/workspaces(.en).md, docs/agent-runs/revisions(.en).md).
  3. 3b0a151 docs: internal/gitserver, cmd/git-server and cmd/git-server-preset READMEs (both languages) call the Git Server code-hub decisions approved, matching specs and docs/repositories/git-server.
  4. 61a1564 Merge of main at 0f4e60b (feat(pluginmarket): agent configuration catalog snapshot and frozen install associations (P2, preflight) #84, feat(protocol): 声明可选 Thread 正文投影与实时预览契约 #87, fix: 阻止收尾后的 Run 工作继续领取和新登记 #61). The codec keeps this branch's invalidInput next to main's boundedSchemaVersion; docs/runtime/controller-integration(.en).md lists both ADRs; the migrations README keeps main's 0045 section before this branch's; internal/controlpb is regenerated (task proto:check clean).
  5. 6d51cad fix(migrations): renumber to 0046/0047 after main's 0045.

Final catch-up with main

  1. 6468f01 Merge of main at 4718aba (feat: 任务持续对话、串行交接与可选实时预览 #86, feat(core): persist the run kickoff in the Start variable pool #95–fix: pass the desktop default agent config through the publish gate #99). Takes main's rewritten module READMEs and code maps, keeps this branch's Git-delivery simulator notes and the WorkflowRun Git Server note, reports gitServer in the router's health line, and drops main's NewDevelopmentStore mention, which this branch removed with the tenant-level clone path. The public request keeps main's new fields without CloneID. Migrations move to 0050/0051 after main's 0049.
  2. 4e5e00f Merge of main at b7e1801 (feat(workflows): start a run from the selected version's own form #70, feat(workflows): 让运行详情与历史随运行状态更新(有界轮询 + 单调合并) #82, test: cover workflow asset import fan-out, user edits and fetch bounds #83, feat(core): settle an in-flight workflow session whose Node is gone #91, feat(core): record agent run cancellation requests #100–feat(model-gateway): support pinned Claude Messages requests #102, feat(core): declare and resolve workflow globals and sys.* variables #104, fix(core): keep unset workflow run timestamps null #105, fix(core): omit the agent declaration association for undeclared plugins #107–fix: 发布期把 file/array[file] global 的遗留路径字符串规范化为 workspace_file 引用 #110). docs/workflows/workflows(.en).md keeps main's node_unavailable and session_turn_deadline_exceeded rules for a WorkflowRun session, followed by this branch's note that the session has no Git Server access. The public request keeps main's AgentPluginID mapping without CloneID. Both upgrade tests stay in integration/migration_upgrade_path_test.go. main took 0050 and 0051, so the two migrations become 0052/0053, with the upgrade test, the migrations README index and the docs renumbered. No proto change since 6468f01; the OpenAPI document and frontend client regenerate with no drift.
  3. 7a1a2af Merge of main at 9814cac (feat(core): settle legacy workflow IssueRuns and prove scheduler crash recovery #113). main took 0052 for the legacy workflow IssueRun settlement, so the two migrations become 0053/0054; the migrations README lists main's 0052 before them, and the upgrade test, its baseline and the docs are renumbered. No proto change.

Verification

  • 7a1a2af (current head): go build ./..., go vet on integration and internal/core, task format:check, the integration migration and upgrade tests (now including main's TestMigration0052LegacyWorkflowIssueRunSettlementAppliesFreshAndUpgrades and TestMigration0053RetiresTenantLevelClonesKeepingWorkspaceClones) and main's new internal/core recovery tests pass on real PostgreSQL. The merge only adds main's feat(core): settle legacy workflow IssueRuns and prove scheduler crash recovery #113 (one migration and its tests) and renumbers, so the remaining gates below were not rerun locally; CI covers the full suite.
  • 4e5e00f (unit-level only): task format:check, task lint (0 issues), task proto:lint, buf generate with no internal/controlpb drift, buf breaking against upstream/main, go run ./cmd/openapi and npm run api:generate with no drift, go build ./... and go vet ./..., go test ./internal/... ./cmd/... on real PostgreSQL (REQUIRE_POSTGRES=1, 33 packages), the integration package's migration and upgrade tests (-run 'TestMigration|TestRevisionShapeKeepsGitAndBundleRowsApart|TestRevisionUpgrade|PersonalAgentConfigurationsUpgrade', 25 tests, including TestMigration0052RetiresTenantLevelClonesKeepingWorkspaceClones), and the frontend's format:check, lint, typecheck, unit tests with coverage (140 files, 1180 tests), check:modules against upstream/main, check:docs, check:dead, check:dup and build pass. The rest of the integration package and the -race suite are left to CI on this head; the full-stack acceptance has not been rerun on it yet (see "Before merge").
  • 6d51cad: task format:check, task lint, task proto:lint, task proto:check, task build, task proto:breaking against upstream/main, task frontend:check, the full suite on real PostgreSQL (go test ./..., 1027 s) and the full suite under -race (1200 s) pass.
  • 3b0a151: the same gates pass (integration package 744 s; -race full suite, no data race).
  • End to end on fresh stacks (new Compose projects, image tags and databases, --internal sandbox networks), built from feat: clone Workspaces from Git Server snapshots and deliver Revisions over Git (internal Git line) #81 at 3b0a151, feat(node): clone from Git Server snapshots, collaborate through ora-git and deliver Revisions over Git desktop#681 b2962ccd and ora-space/cluster#29 3645159; 59 checks, all PASS:
Suite Result Time
workspace-git:acceptance 26/26 401 s
revision:acceptance 2/2 110 s
revision:resume:acceptance 3/3 170 s
agent:session:acceptance 9/9 70 s
runtime:acceptance 8/8 126 s
cross-line:acceptance (base + agent fixture + external Git + cross-line overlays) 11/11 90 s

The acceptance uses cloud#81 3b0a151, the head before its merge of #84 from main. #84 freezes agentConfiguration into plugin install inputs, and a Controller built against an older contract drops it, so Cloud refuses the plugin dispatch (dispatch ownership conflict). ora-space/desktop#698 fixed this on desktop main, and desktop#681 now carries it.

Before merge

The three PRs have caught up with main together: #81 at 7a1a2af, ora-space/desktop#681 at c08770ed (pins third_party/cloud to 7a1a2af) and ora-space/cluster#29 at b59d700. Still to do before the owner merges:

  1. Rerun the full-stack acceptance on these heads: workspace-git, revision, revision:resume, agent:session, runtime, cross-line, plugin:acceptance and opencode:m4:acceptance.
  2. The landing specs PR (ADRs to implemented, core test case evidence) is open.
  3. A re-review of the catch-up. If main takes another migration number before this merges, the two migrations move after it again.

Then cloud#81, desktop#681 (re-pinned to the merged cloud commit) and cluster#29 merge in that order.

Documentation

Written into the current docs (both languages): docs/runtime/workspaces, docs/repositories/git-server, docs/agent-runs/revisions, docs/runtime/controller-integration, docs/core/persistence, docs/architecture, docs/operations/configuration, docs/operations/deployment, docs/development/local-development, docs/agent-runs/issue-runs, docs/runtime/runtime-control. The root README is unchanged.

Breaking switch

No feature flag and no migration of business state: Workspaces only clone from snapshots after this lands. Snapshots come from the external line's syncs (repository.enabled) or, in development and acceptance, from git-server-preset. Development data is rebuilt.

Not in this PR

  • Syncing external repositories into snapshots and Publish: they are the external line, already on main (cloud#76) and merged here (commit 17).

@EricWvi EricWvi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main 已合入 cloud#85:docs/ 按领域整体重建为中英双语,文档地图在 docs/README.md,旧的 docs/*.md 已经全部删除。同时 cloud#62 已合入迁移 0038_agent_workspace_blocked_deadline.sql。请先合并或 rebase 最新 main,再做以下适配:

  • 迁移编号:main 上最新的迁移已经是 0038。请把本 PR 新增的迁移顺延到合并时 main 最新编号之后,同步改测试里的文件名、测试名和升级基线,并在 internal/core/migrations/README(.en).md 末尾追加对应小节(两个文件现在和 main 冲突)。(本 PR 新增 0038_retire_tenant_level_clones、0039_git_delivery_refs,两个都要顺延)。
  • 旧文档已删除,本 PR 对它们的修改请改到新文档:
    • docs/runtime-control*.md → docs/runtime/runtime-control(.en).md
    • docs/execution-contract.md → docs/runtime/workspaces(.en).md(Workspace、clone)
    • docs/core-contract.md → docs/core/persistence(.en).md,或对应领域的文档
    • docs/agent-run-control-plane-review*.md → docs/agent-runs/revisions(.en).md(Revision 交付与续接)
    • docs/development/agent/* 不再保留,接口以 api/openapi.json 为准,数据库结构以迁移为准
  • Git 交付路径:请更新 docs/repositories/git-server(.en).md(ref 查询、交付 ref)和 docs/agent-runs/revisions(.en).md(Revision 改走 Git、bundle 退役)。新文档目前写的是"Cloud 不调用 ref 查询""Revision 用 bundle",需要按本 PR 的行为改写,同时说明对应 ADR 的状态。
  • 冲突:根 README(.en).md 已改写成入口页,本 PR 的说明请放进对应文档,不要加回 README;internal/simulator/README(.en).md 新增了 Substrate 替身接口表;internal/controlpb/operations.pb.go 请在合并后用 task proto:generate 重新生成,不要手工解冲突。
  • 文档规则见 AGENTS.md 的 Documentation 一节:中英两版同步修改;只写当前代码能核验的事实;接口字段以 api/openapi.json 为准;进度和验收记录写在 issue 里,不进仓库。

…e wire

Map the replaced Internal Control contract onto Cloud's durable shapes:

- CloneSpec is the four snapshot fields {repositoryUrl, snapshotRef,
  baseCommit, workspaceRef}; the codec rejects a repository URL that is not
  plain https ending in .git, a snapshot ref outside the Binding snapshot
  namespace or naming another commit, and a Workspace ref outside
  refs/heads/workspaces/<id>/ or naming HEAD.
- OperationSnapshot carries the clone step's clone_input; OperationProject
  carries only the Project id.
- PriorRevision names the Git repository, delivery ref and base commit;
  DeliverRevisionSpec carries gitRepositoryUrl, deliveryRef and
  workspaceRef instead of a bundle key; RevisionDelivered has no bundle.
- AgentSessionSpec carries the Workspace directory.
- GrantRevisionDownload is gone.

Add core.GitServer (the repository base URL and ref resolver a Store uses)
and a Git Server double to the simulator: the simulated Controller forwards
the frozen clone input, the simulated Node fetches the snapshot into a
remote-less checkout on the Workspace branch, and a delivery pushes its
final commit to its delivery ref and fast-forwards the Workspace branch.
The integration fixture runs on the double. Cloud starts freezing and
checking these inputs in the following commits.
Add the git_server configuration section (Revision D2): the sandbox-facing
repository_base_url written into execution inputs, and the ref query
listener Cloud verifies refs through with its own pinned client
certificate. Startup validates the section and loads the files without a
network call; an empty repository_base_url runs Cloud without a Git
Server. Every key has a CLOUD_GIT_SERVER_* override.

internal/gitrefquery is the read-only client of GET /internal/v1/refs: it
resolves one exact ref, treats a definitive absence as
core.ErrGitRefNotFound and every other failure as unavailable, and never
follows redirects. The server wires it into store.GitServer, and /healthz
reports gitServer configured or unconfigured beside objectStore.
A Workspace's clone step no longer clones the Project's external
repository (operation decision "clone step consumes the Binding
snapshot"):

- D1: the transaction that enters the clone step, and every claim of a
  step not yet frozen, freezes request.clone from the Binding's current
  snapshot: the Project's Git Server repository, the snapshot ref, its
  commit and refs/heads/workspaces/<id>/<branch>. The input is frozen once
  per operation; every execution, retries included, must carry it
  verbatim, and the claim snapshot hands it out as cloneInput. The
  Controller's Project view drops the repository and credential fields.
- D2: without a snapshot the claim reads the snapshot and the Binding's
  latest sync in one statement: an unfinished sync parks the step as
  retry_wait snapshot_not_ready without spending an attempt; a sync that
  ended without one fails it as repository_sync_failed, recording the sync
  and its code, and a failed create_project leaves the Project active. A
  parked operation never empties a claim. Without a Git Server the step
  blocks as git_server_unconfigured. Run preparation shows these codes.
- D3: a clone_ready result must report exactly the input's base commit,
  which becomes the Workspace baseline. An isolated Workspace's baseRef may
  only be omitted, empty, HEAD or the Binding branch (base_ref_not_synced
  otherwise), and a Project's default branch must be usable in a ref.
- D6: delete_project is not handed out to quiesce while a sync or publish
  of the Project is unfinished (retry_wait repository_operation_running).
- No external repository credential gates the clone any more.
- The public operation view hides the frozen input and the sync's
  Operation ID; it keeps the sync's safe error code.

git-server-preset completes the Binding's unfinished sync when it records
a snapshot, so fixtures stand in for the external line's first sync.
Every clone is now the clone step of a Workspace operation (operation
decision D5, invariant 8). Remove the public /clones routes, their
OpenAPI schemas and the frontend Repositories page, the clone request
registry and its ClaimWork path, and the development store that kept the
retired fixture alive. ClaimWork returns only Agent session and Revision
delivery work, and a dispatch naming no Workspace operation is not found.

Migration 0039 deletes clone executions that belong to no Workspace and
their receipts, drops clone_executions.clone_request_id and its index,
makes clone_executions.workspace_id NOT NULL and drops clone_requests.

BREAKING CHANGE: /api/v1/tenants/{tid}/clones is gone; existing tenant
clone requests are deleted.
Implement the Git-native Revision decisions (cloud/revision
20261017 "Git-native delivery refs and resume", controller-integration
20261016 "snapshot clone input and execution ref grants" D6, D8, D9; both
proposed):

- A delivery work item fixes its gitRepositoryUrl, its own deliveryRef
  refs/ora/deliveries/<workId> and the run Workspace's workspaceRef (taken
  from the checkout's clone input) beside the history key; no bundle key
  exists any more. Delivery needs both the object store and the Git
  Server and is skipped with object_store_unconfigured or
  git_server_unconfigured otherwise.
- Cloud verifies a delivered or unchanged result outside the transaction:
  the delivery ref, queried on the Git Server, must name the final commit,
  and the history object must match its declared size and digest. Then it
  registers the Revision with its delivery ref. An unreachable Git Server
  refuses the takeover as unavailable without writing anything. Upload
  grants sign only the history key; push_rejected and push_failed are new
  failure reasons and bundle_failed is refused in new results.
- A follow-up run resumes the Issue's latest Revision that has a verified
  delivery ref and moved off its base commit, only from the repository
  its checkout was cloned from. Its priorRevision names the Git
  repository, delivery ref and base commit; a failed fetch of the
  delivery ref refuses the Revision for later selection unless the run
  was being cancelled.
- Migration 0040 adds revisions.delivery_ref with a shape constraint that
  keeps Git and legacy bundle rows apart and a unique index per ref.
- The public run projection derives `changed` from Cloud's verdict and
  reports a null bundleSize for Git Revisions; the Issue page no longer
  shows a bundle size.
Map each execution a sandbox declares to its Git Server grant (contract
D5, D6); every granted execution reads the whole Project repository:

- A Workspace clone reads, and writes nothing, only while it has no
  result, its operation is running in the clone step, the actor can still
  use the runtime, no force stop is pending or has terminated it, its Node
  is the Workspace's current Node and its input names the requested
  repository. Main Workspaces clone while their Project is provisioning.
- Every live Agent session reads, and may create or fast-forward branches
  under its own Workspace's refs/heads/workspaces/<id>/ prefix; the prefix
  comes from the certificate, never the request.
- A Revision delivery creates only the delivery ref of its input and may
  fast-forward the input's workspaceRef when it belongs to the
  certificate's Workspace.

The Git Server integration harness is shared by the clone, session and
delivery cases, and the delivery case now verifies the pushed ref through
the real ref query before registering the Revision.
A session work item now carries the Project's Workspaces, newest first and
at most 100, fixed when the item is released (contract D7): each listing
names the Workspace and its kind (main, isolated or run), and a run
Workspace also its Issue, title, run and run status. Run Workspaces stay
listed after deletion because their branches remain on the Git Server;
deleted isolated Workspaces and other Projects' Workspaces are not
listed. The directory only helps `ora-git list` find branches and takes
no part in authorization.
Bring the documents in line with Workspaces cloned from Binding
snapshots, the retired tenant clones and Revisions delivered over Git:

- docs/runtime/workspaces: the clone step consumes the Binding's frozen
  snapshot input, how it waits or fails without a snapshot, baseRef and
  requested_ref semantics, credentials no longer gating Node work, and
  the removed tenant clone API.
- docs/repositories/git-server: clone, session and delivery grants, and
  Cloud verifying delivery refs through the ref query.
- docs/agent-runs/revisions: delivery over Git, verification by ref query,
  resume from the prior's delivery ref, and the retired bundles and
  download grant.
- docs/runtime/controller-integration, docs/core/persistence,
  docs/architecture, docs/operations, docs/development and the run and
  runtime-control documents: the snapshot clone input, the git_server
  settings and health report, and the simulator's Git Server double.

The decisions behind this are still proposed, and the documents say so.
Also bring internal/core's README up to date, list the already merged
migration 0037 in the migrations catalog, and describe the new
integration tests.
@ObsisMc
ObsisMc force-pushed the feat/183-internal-git-line branch from 5769b5e to 6c32c69 Compare October 19, 2026 02:16
Renumber this line's migrations after main's 0039-0042 workflow migrations:
0039_retire_tenant_level_clones -> 0043, 0040_git_delivery_refs -> 0044, with
the upgrade test, migration READMEs and docs following. The claim keeps main's
claimed_run_id projection for workflow work and drops the retired tenant clone
request branch; the public request no longer carries CloneID.
Revision delivery no longer makes bundles, so REVISION_FAILURE_REASON_BUNDLE_FAILED
is removed and both its value 4 and its name are reserved, matching how
executions.proto retired CLONE_FAILURE_REASON_BRANCH_NOT_FOUND. A Node that still
sends 4 is refused like any reason outside the closed set; an integration test pins
that at the gRPC boundary.
…irectory

A WorkflowRun's Agent session gets no Git Server access in the first phase and
the directory has no fields for it (controller-integration D5, D7), so the
directory query skips Workspaces owned by a WorkflowRun. The Git Server already
denied such sessions because the grant only joins IssueRun executions; an
integration test now pins that by moving a granted session to a WorkflowRun and
asserting its read and push both get 403. Docs describe both.
Operation D2 now keeps no copy of the failed sync's error code on the operation:
awaitSnapshot records just syncOperationId, and a run's preparation.syncErrorCode
reads that sync's own error_code from repository_operations, within the
Workspace's Project. Without a recorded ID it still falls back to the Binding's
latest failed sync. The public operation result therefore carries neither field,
so OperationResult drops syncErrorCode; OpenAPI, the generated client, tests and
docs follow.
specs#111 merged, so the snapshot clone input and execution ref grants, the clone
step consuming the Binding snapshot, and the Git-native delivery refs ADRs are
approved (not yet implemented). Drop the proposed and under-review wording in
both languages.
Keeps both Store fields (GitServer and main's ModelEgress) and lists both the
gitServer readiness field and main's egress headers for Cloud's /healthz in the
deployment docs.
Brings in the external Git line (repo-executor, Credential Store, repository
sync and explicit publish, migration 0043_external_git_line.sql) and the
shared deployment egress policy.

- Renumber this branch's migrations after main's 0043:
  0044_retire_tenant_level_clones.sql and 0045_git_delivery_refs.sql.
- Publishing a Revision uses its verified delivery_ref, never the Node-local
  revision_ref, and is covered by an integration test.
- Keep both git_server.* and repository.* configuration, the executor-slot
  route parameter and the snapshot-based clone of credentialed Projects.
- Regenerate api/openapi.json and the frontend client.
…rojects

The internal line's fixture settles every new Project's first sync from its
source repository, so a Project is active only after its snapshot exists.
Sync and publish cases that need an active Project now race for a sync a
member asked for, the delete-waits publish case gives the Binding the
credential a publish names, and a route test pins the executor-slot :slot
parameter that the merge restored.
The publish ADR (D1) has Cloud confirm through the ref query that the source
ref exists and leaves the source commit's reachability to the executor; the
code checks existence only. The docs claimed Cloud confirmed the ref named the
source commit.

@wanglongan587 wanglongan587 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查结论:Request changes

审阅 commit:72cfac1(对应 specs#111 已合并的五篇 ADR,状态均为 approved)。

Cloud 侧主体实现与 ADR 一致:clone 输入在进入步骤与领取时冻结一次、snapshot_not_ready 等待不登记/不耗次数、repository_sync_failed 只记同步 ID、领取跳过停放、delete_project 等同步与发布、按执行类型的 Git 授权、交付的 ref 查询核验与续作选取、迁移与前端删除都有对应代码和测试。以下问题需要处理后重新请审。

阻塞

  1. 落后 main 且有冲突。 当前 mergeable = CONFLICTING,main 已到 7cf4cda(含 #92、#93、#94、#56)。

    • 冲突文件:internal/api/router/router.go、integration/migration_upgrade_path_test.go、internal/core/migrations/README(.en).md。
    • #94 已修复 SlotName 绑定;本 PR 的 1668ab5 是同一修复并新增了 integration/executor_slot_route_test.go。解决时保留 main 的修复,删掉重复的测试(或说明为何两边都保留)。
    • #93 在 migration_upgrade_path_test.go 新增了 TestMigration0044ModelAttemptWorkflowRunAppliesFreshAndUpgrades,与本 PR 的 0044 测试在同一位置;合并后两个测试都要保留。
    • 合并后重跑 task check、go test -race ./...、task build、task proto:check、task proto:breaking、task frontend:check,并重新跑全栈验收。
  2. 迁移编号与 main 撞号。 main 已有 internal/core/migrations/0044_model_attempt_workflow_run.sql;本 PR 仍新增 0044_retire_tenant_level_clones.sql 和 0045_git_delivery_refs.sql,不符合“合并前按 main 最新编号顺延”。

    • 顺延为 0045、0046(合并时再按当时 main 最新编号核对),同步:TestMigration0044… 的测试名与基线、internal/core/migrations/README(.en).md、docs/runtime/workspaces(.en).md 中写死的 0044、PR 描述的 Migrations 段。
  3. 落地 specs PR 的时机。 描述写的是“After this PR merges, a follow-up specs PR moves the three ADRs to implemented”。按“三个运行”,实现 PR review 通过后、产品 PR 合并前就应开出运行 3 的 specs PR(五篇 ADR 改为 implemented、同步核心用例证据),产品 PR 合并后再合并它。请在本轮 review 通过后、合并前打开并链接到本 PR 和 #183。

应修

  1. internal/gitserver/README(.en).md、cmd/git-server-preset/README(.en).md 仍写“proposed 的后续决策…”,但该 ADR 已 approved,且同 PR 的 docs/repositories/git-server(.en).md 标了 (approved)。本 PR 已改动这些 README,请顺手把四处改成 approved。

  2. PR 描述与当前 head 不符:head 已是 72cfac1(只改两个 md),实际 20 个提交含 3 个 merge(1750af7、b9f569f、afd6b00);描述只列 18 项,Migrations 段仍写 0043。合并 main、顺延迁移后一起重写 Commits / Migrations / 验证结论。

建议(可不动)

  1. revision_delivery_skips 只记录 run_id,object_store_unconfigured / git_server_unconfigured 的原因没有持久化:internal/core/execution_work.go 把 reason 传给 deliverySettled 后,internal/core/agent_run_delivery.go 的 skipped 分支把它丢掉了。ADR D2 写的是“原因…记为…”。如果运维需要区分两种原因,补一列或写进 run result;否则在文档里说明原因只出现在结算事件里。

审查范围基于 72cfac1;上述问题处理后会按新 head 重新审。

Keep main's executor-slot route test from ora-space#94 and drop this branch's
duplicate; keep both 0044 upgrade tests.
…'s 0044

main took 0044 for model_attempt_workflow_run, so the tenant-level clone
retirement becomes 0045 and the Git delivery refs become 0046.
Keep both sides of the codec helpers, the controller-integration ADR
links and the migrations README; regenerate internal/controlpb.
…'s 0045

main took 0045 for agent_configuration_catalog, so the tenant-level clone
retirement becomes 0046 and the Git delivery refs become 0047.

@wanglongan587 wanglongan587 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审结论:Approve(针对 head 6d51cad;合并前仍需机械性追平)

审阅 commit 6d51cad(base main)。本轮为只读复核:重读了上一轮四项意见对应的代码、两次 merge 的解冲突点,并抽查了 router、迁移测试、两份 migrations README、docs、OpenAPI 与 proto;没有重跑 Go 门禁和全栈验收,端到端证据来自 PR 描述与 #183 的汇报。

上一轮意见逐项核对

  1. 合入 main、解冲突:4b772e6(#92–#94、#56)与 61a1564(#84、#87、#61)都在。
    • internal/api/router/router.go:PublicRequest 不再有 CloneID,SlotName 与 main 一致,/me/executor-slot-mappings/{slot} 的 PUT/DELETE 都在。
    • integration/executor_slot_route_test.go 已删除,main 的 TestExecutorSlotMappingHTTPBindsSlotPath 保留。
    • integration/migration_upgrade_path_test.go 同时保留了 main 的 TestMigration0044ModelAttemptWorkflowRunAppliesFreshAndUpgrades 和本线的 TestMigration0046RetiresTenantLevelClonesKeepingWorkspaceClones。
    • 抽查解冲突的代码:execution_codec.go 同时保留本线的 invalidInput 与 main 的 boundedSchemaVersion;execution_work.go 保留 main 的 claimed_run_id 投影;operation result 的 syncErrorCode 已从 OpenAPI 移除,preparation.syncErrorCode 保留。
  2. 迁移顺延:head 上是 0046_retire_tenant_level_clones.sql / 0047_git_delivery_refs.sql,升级测试名与基线、internal/core/migrations/README(.en).md、docs/runtime/workspaces(.en).md、docs/agent-runs/revisions(.en).md 都一致;仓库里搜不到这条线旧的 0043/0044/0045 文件名。
  3. ADR 状态:internal/gitserver、cmd/git-server、cmd/git-server-preset 的中英 README 都已是 approved。我按 specs main 3bde9f1 核对,五篇内部线 ADR 仍都是 approved。
  4. 描述:提交列表 25 项、head、Migrations 段都与实际一致;仅“Before merge”一节的迁移编号已过时(见下)。

上一轮第 6 条(revision_delivery_skips 只记 run_id、原因不落库)仍未处理。我当时标为“建议(可不动)”,本轮不阻塞;如果决定保留现状,请在落地运行的文档里写清原因只出现在结算事件里。

合并前必须满足(不改变本轮 Approve,但会让 head 变化)

  1. 追平 main 并按规则顺延迁移。 当前 main 已到 4718aba,本 PR 落后 48 个提交、CONFLICTING;main 的迁移已到 0049_thread_commands_workflow_run.sql,所以不是描述里写的 0049/0050,而是 0050/0051,合并时再按当时 main 核一次。测试名/基线、两份 migrations README、docs 与描述一起改。
  2. 重新锁定契约并重跑验收。 6d51cad 的 proto 已含 main 的 agent_configuration(PluginAgentConfiguration),而 desktop#681 仍锁 a51ee11(没有这个字段),所以本轮全栈验收用的是 cloud 3b0a151。cloud#81 合并后 desktop 要改锁并重新生成;最终三仓 head 上重跑门禁与全栈验收,建议补 plugin:acceptance 与 agent:session,因为插件派发正是 #84/desktop#698 改动的地方。
  3. 落地 specs PR:按“三个运行”,review 通过后、产品 PR 合并前开出五篇 ADR → implemented 的 specs PR(同步核心用例证据),产品 PR 合并后再合并它;owner 合并前确认它已存在。
  4. 追平并 push 后重新打 status:in-review(会清掉 review:lgtm),我按增量复审。不要用本轮 lgtm 合并追平后的 head。

说明

  • 本轮的改动(合 main、顺延编号、README 状态)没有引入我在只读复核中能发现的代码缺陷;剩余项都是合并前的机械步骤。

Resolve against main's rewritten module READMEs: take main's code maps,
keep this branch's Git-delivery simulator notes and the WorkflowRun Git
Server note, report gitServer in the router's health line, and drop
main's NewDevelopmentStore mention, which this branch removed with the
tenant-level clone path. The public request and router keep main's new
fields without CloneID; main's accepted clone signal is gone with the
clone route. Migrations move to 0050/0051 after main's 0049, with the
upgrade test, the migrations README index and docs renumbered.
ObsisMc added a commit to ObsisMc/desktop that referenced this pull request Oct 20, 2026
Re-pin third_party/cloud to ora-space/cloud#81 6468f01, which carries
main's contract (agent_configuration, Thread previews) next to the Git
line's, and regenerate the client. Main's new Thread-preview code drops
the retired download-grant relay; its preview tests use the Git Server
fixture and the session spec's workspace directory; the duplicate
record_provisioning_fact stub keeps main's.
Keep both sides of the WorkflowRun session paragraph in the workflow docs:
main's node_unavailable and session_turn_deadline_exceeded rules, then
this branch's note that the session has no Git Server access. The public
request keeps main's AgentPluginID mapping without CloneID. Both upgrade
tests stay in migration_upgrade_path_test.go. main took 0050 and 0051, so
the tenant-level clone retirement becomes 0052 and the Git delivery refs
become 0053, with the upgrade test, the migrations README index and docs
renumbered.
ObsisMc added a commit to ObsisMc/desktop that referenced this pull request Oct 21, 2026
Move third_party/cloud from 6468f01 to 4e5e00f, the head of
ora-space/cloud#81 after its last merge of Cloud main. The proto is
unchanged between the two, so the generated client is identical.
main took 0052 for the legacy workflow IssueRun settlement, so the
tenant-level clone retirement becomes 0053 and the Git delivery refs
become 0054. The migrations README lists main's 0052 before them; the
upgrade test, its baseline and the docs are renumbered.
ObsisMc added a commit to ObsisMc/desktop that referenced this pull request Oct 21, 2026
Move third_party/cloud from 4e5e00f to 7a1a2af, the head of
ora-space/cloud#81 after its latest merge of Cloud main. The proto is
unchanged, so the generated client is identical.

@EricWvi EricWvi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10-18 的意见已在 10-19 处理;owner 增量复审了追平 main 的冲突处理(6d51cad..7a1a2af)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants