sequence-base 0.3.12__tar.gz → 0.3.13__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. {sequence_base-0.3.12 → sequence_base-0.3.13}/PKG-INFO +1 -1
  2. {sequence_base-0.3.12 → sequence_base-0.3.13}/pyproject.toml +6 -1
  3. sequence_base-0.3.12/.github/workflows/ci.yml +0 -32
  4. sequence_base-0.3.12/docs/platform/README.md +0 -66
  5. sequence_base-0.3.12/docs/platform/REVIEW.md +0 -86
  6. sequence_base-0.3.12/docs/platform/START.md +0 -366
  7. sequence_base-0.3.12/docs/platform/accounts.md +0 -162
  8. sequence_base-0.3.12/docs/platform/billing.md +0 -116
  9. sequence_base-0.3.12/docs/platform/build/BUILD_LOG.md +0 -222
  10. sequence_base-0.3.12/docs/platform/build/goal_sha256.json +0 -31
  11. sequence_base-0.3.12/docs/platform/build/gs-build-wave.js +0 -163
  12. sequence_base-0.3.12/docs/platform/build/gs-spec-goals.js +0 -41
  13. sequence_base-0.3.12/docs/platform/container.md +0 -55
  14. sequence_base-0.3.12/docs/platform/contracts.md +0 -233
  15. sequence_base-0.3.12/docs/platform/deploy/PLAN.md +0 -93
  16. sequence_base-0.3.12/docs/platform/deploy/PROD_REORG.md +0 -78
  17. sequence_base-0.3.12/docs/platform/deploy/SCHEMA_COMPAT.md +0 -38
  18. sequence_base-0.3.12/docs/platform/deploy/archive/sequences-gw.genseq-506918.20261001.yaml +0 -109
  19. sequence_base-0.3.12/docs/platform/eval.md +0 -102
  20. sequence_base-0.3.12/docs/platform/gateway.md +0 -80
  21. sequence_base-0.3.12/docs/platform/goals/A1.yaml +0 -39
  22. sequence_base-0.3.12/docs/platform/goals/A2.yaml +0 -26
  23. sequence_base-0.3.12/docs/platform/goals/A3.yaml +0 -24
  24. sequence_base-0.3.12/docs/platform/goals/C1.yaml +0 -32
  25. sequence_base-0.3.12/docs/platform/goals/C2.yaml +0 -27
  26. sequence_base-0.3.12/docs/platform/goals/C3.yaml +0 -22
  27. sequence_base-0.3.12/docs/platform/goals/C4.yaml +0 -22
  28. sequence_base-0.3.12/docs/platform/goals/C5.yaml +0 -34
  29. sequence_base-0.3.12/docs/platform/goals/G1.yaml +0 -30
  30. sequence_base-0.3.12/docs/platform/goals/G2.yaml +0 -26
  31. sequence_base-0.3.12/docs/platform/goals/G3.yaml +0 -32
  32. sequence_base-0.3.12/docs/platform/goals/G4.yaml +0 -45
  33. sequence_base-0.3.12/docs/platform/goals/G5.yaml +0 -43
  34. sequence_base-0.3.12/docs/platform/goals/O1.yaml +0 -19
  35. sequence_base-0.3.12/docs/platform/goals/O2.yaml +0 -27
  36. sequence_base-0.3.12/docs/platform/goals/O3.yaml +0 -28
  37. sequence_base-0.3.12/docs/platform/goals/O4.yaml +0 -25
  38. sequence_base-0.3.12/docs/platform/goals/O5.yaml +0 -30
  39. sequence_base-0.3.12/docs/platform/goals/R1.yaml +0 -30
  40. sequence_base-0.3.12/docs/platform/goals/R2.yaml +0 -23
  41. sequence_base-0.3.12/docs/platform/goals/R3.yaml +0 -30
  42. sequence_base-0.3.12/docs/platform/goals/S1.yaml +0 -32
  43. sequence_base-0.3.12/docs/platform/goals/S2.yaml +0 -30
  44. sequence_base-0.3.12/docs/platform/goals/S3.yaml +0 -30
  45. sequence_base-0.3.12/docs/platform/goals/S4.yaml +0 -30
  46. sequence_base-0.3.12/docs/platform/goals/S5.yaml +0 -56
  47. sequence_base-0.3.12/docs/platform/goals/S6.yaml +0 -34
  48. sequence_base-0.3.12/docs/platform/goals/V1-storage.md +0 -26
  49. sequence_base-0.3.12/docs/platform/goals/V2-user-quotas.md +0 -27
  50. sequence_base-0.3.12/docs/platform/goals/W0.1.yaml +0 -30
  51. sequence_base-0.3.12/docs/platform/goals/W0.2.yaml +0 -21
  52. sequence_base-0.3.12/docs/platform/modal/README.md +0 -26
  53. sequence_base-0.3.12/docs/platform/modal/architecture.md +0 -27
  54. sequence_base-0.3.12/docs/platform/modal/connect.md +0 -41
  55. sequence_base-0.3.12/docs/platform/modal/cost.md +0 -52
  56. sequence_base-0.3.12/docs/platform/modal/custom-domain.md +0 -47
  57. sequence_base-0.3.12/docs/platform/modal/debugging.md +0 -42
  58. sequence_base-0.3.12/docs/platform/modal/goals.md +0 -92
  59. sequence_base-0.3.12/docs/platform/modal/limits.md +0 -50
  60. sequence_base-0.3.12/docs/platform/modal/plan.md +0 -65
  61. sequence_base-0.3.12/docs/platform/modal/white-label.md +0 -33
  62. sequence_base-0.3.12/docs/platform/modal/wiring.md +0 -36
  63. sequence_base-0.3.12/docs/platform/observability.md +0 -128
  64. sequence_base-0.3.12/docs/platform/references.md +0 -48
  65. sequence_base-0.3.12/docs/platform/sdk.md +0 -246
  66. sequence_base-0.3.12/tests/test_codec_roundtrip.py +0 -133
  67. sequence_base-0.3.12/tests/test_contracts.py +0 -816
  68. sequence_base-0.3.12/tests/test_weights_parts.py +0 -62
  69. {sequence_base-0.3.12 → sequence_base-0.3.13}/.gitignore +0 -0
  70. {sequence_base-0.3.12 → sequence_base-0.3.13}/README.md +0 -0
  71. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/__init__.py +0 -0
  72. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/auth.py +0 -0
  73. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/codec/__init__.py +0 -0
  74. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/codec/image.py +0 -0
  75. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/codec/resize.py +0 -0
  76. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/constants/__init__.py +0 -0
  77. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/constants/env.py +0 -0
  78. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/constants/headers.py +0 -0
  79. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/constants/version.py +0 -0
  80. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/__init__.py +0 -0
  81. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/accounts.py +0 -0
  82. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/act.py +0 -0
  83. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/benchmarks.py +0 -0
  84. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/connect.py +0 -0
  85. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/deployments.py +0 -0
  86. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/errors.py +0 -0
  87. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/eval.py +0 -0
  88. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/flags.py +0 -0
  89. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/io.py +0 -0
  90. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/policy.py +0 -0
  91. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/contract/volumes.py +0 -0
  92. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/errors/__init__.py +0 -0
  93. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/errors/transport.py +0 -0
  94. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/obs/__init__.py +0 -0
  95. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/obs/log.py +0 -0
  96. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/obs/rid.py +0 -0
  97. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schema_export.py +0 -0
  98. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ActionChunk.json +0 -0
  99. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ActionContract.json +0 -0
  100. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ActionStep.json +0 -0
  101. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/AdapterTransform.json +0 -0
  102. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Autoscaler.json +0 -0
  103. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/BenchmarkConditionSpec.json +0 -0
  104. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/BenchmarkRegisterRequest.json +0 -0
  105. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/BenchmarkSpec.json +0 -0
  106. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/BenchmarkStatusResponse.json +0 -0
  107. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/BootstrapResponse.json +0 -0
  108. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Camera.json +0 -0
  109. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ClampInfo.json +0 -0
  110. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/CodeBundle.json +0 -0
  111. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Concurrency.json +0 -0
  112. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Conditions.json +0 -0
  113. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ConnectRequest.json +0 -0
  114. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ConnectResponse.json +0 -0
  115. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/DeploymentAccepted.json +0 -0
  116. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/DeploymentPolicy.json +0 -0
  117. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/DeploymentRequest.json +0 -0
  118. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/DeploymentStatusResponse.json +0 -0
  119. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Embodiment.json +0 -0
  120. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ErrorBody.json +0 -0
  121. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Estimate.json +0 -0
  122. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/EvalDryRunResponse.json +0 -0
  123. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/EvalReport.json +0 -0
  124. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/EvalRequest.json +0 -0
  125. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/EvalResponse.json +0 -0
  126. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ImageFrame.json +0 -0
  127. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ImageSpec.json +0 -0
  128. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ImageStepApt.json +0 -0
  129. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ImageStepEnv.json +0 -0
  130. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ImageStepRun.json +0 -0
  131. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ImageStepUvPip.json +0 -0
  132. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/InferParam.json +0 -0
  133. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Lease.json +0 -0
  134. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/LossyTransform.json +0 -0
  135. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/MetricAgg.json +0 -0
  136. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Observation.json +0 -0
  137. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/ObservationContract.json +0 -0
  138. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/PolicyRegistration.json +0 -0
  139. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/PolicySpec.json +0 -0
  140. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Proprioception.json +0 -0
  141. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/RenderSpec.json +0 -0
  142. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Resources.json +0 -0
  143. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/RolloutResult.json +0 -0
  144. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/SecretCreateRequest.json +0 -0
  145. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/SecretInfo.json +0 -0
  146. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/SecretRef.json +0 -0
  147. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/SeqFlags.json +0 -0
  148. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Step.json +0 -0
  149. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/SuiteAgg.json +0 -0
  150. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/TaskAgg.json +0 -0
  151. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Timeouts.json +0 -0
  152. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/UploadTarget.json +0 -0
  153. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/UsageReport.json +0 -0
  154. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/Variant.json +0 -0
  155. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/VolumeAttach.json +0 -0
  156. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/VolumeFile.json +0 -0
  157. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/VolumeInfo.json +0 -0
  158. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/VolumeMount.json +0 -0
  159. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/VolumeRef.json +0 -0
  160. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/VolumeUploadRequest.json +0 -0
  161. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/VolumeUploadResponse.json +0 -0
  162. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/schemas/WarmingError.json +0 -0
  163. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/telemetry/__init__.py +0 -0
  164. {sequence_base-0.3.12 → sequence_base-0.3.13}/sequence_base/telemetry/events.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sequence-base
3
- Version: 0.3.12
3
+ Version: 0.3.13
4
4
  Summary: Shared foundation for the Sequences platform — wire contract, correlation, error taxonomy, constants. Used by the robot SDK, gateway, and container harness.
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: pydantic>=2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sequence-base"
3
- version = "0.3.12"
3
+ version = "0.3.13"
4
4
  description = "Shared foundation for the Sequences platform — wire contract, correlation, error taxonomy, constants. Used by the robot SDK, gateway, and container harness."
5
5
  requires-python = ">=3.11"
6
6
  dependencies = ["pydantic>=2.0"]
@@ -18,3 +18,8 @@ build-backend = "hatchling.build"
18
18
 
19
19
  [tool.hatch.build.targets.wheel]
20
20
  packages = ["sequence_base"]
21
+
22
+ # The sdist is an allowlist: without one hatchling packs the whole repo, and 0.3.0-0.3.12 shipped the
23
+ # internal platform docs to PyPI.
24
+ [tool.hatch.build.targets.sdist]
25
+ include = ["/sequence_base", "/README.md", "/pyproject.toml"]
@@ -1,32 +0,0 @@
1
- # Run the test suite on every push and pull request.
2
- #
3
- # In one sentence: install the [codec] extra (pillow + numpy) and run pytest, so the codec
4
- # round-trip / geometry drift guard runs on every change — base is what the SDK, gateway, and
5
- # container all build on, so a break here breaks all three.
6
- #
7
- # Upstream trigger — push to main, or any pull request
8
- # Downstream effect — a red check on the commit / PR
9
- name: CI
10
-
11
- on:
12
- push:
13
- branches: [main]
14
- pull_request:
15
-
16
- permissions:
17
- contents: read
18
-
19
- jobs:
20
- test:
21
- runs-on: ubuntu-latest
22
- steps:
23
- - uses: actions/checkout@v4
24
- - uses: actions/setup-python@v5
25
- with:
26
- python-version: "3.12" # base is requires-python >=3.11
27
- - name: Install
28
- run: |
29
- python -m pip install -q --upgrade pip
30
- python -m pip install -q -e '.[codec,test]'
31
- - name: Test
32
- run: python -m pytest -q
@@ -1,66 +0,0 @@
1
- # GS deploy platform — 设计总览(Modal-way,GCP-first)
2
-
3
- > 本文件夹是**三个 repo(gateway / container / sdk)统一设计文档**的入口。canonical 设计在此(sequence-base 是三方都 import 的共享仓,放这不漂移)。两个 session 协同:一侧做 SDK(用户面),一侧做 container/GPU/gateway/GCP(runtime + control plane);契约见 [contracts.md](contracts.md),eval / CI-CD 半边见 [eval.md](eval.md),账户 / secret 机制见 [accounts.md](accounts.md),定价 / 成本 / 统一费率表 / GCP 成本硬闸见 [billing.md](billing.md),debugging / latency / telemetry 见 [observability.md](observability.md),全部参考见 [references.md](references.md)。**怎么建(workflow + subagent 执行计划、WU 依赖图)→ [START.md](START.md)。**
4
-
5
- ## 我们要造什么(一句话)
6
-
7
- 让用户把**自己训好的 policy(如 fine-tuned pi0.5:一个 checkpoint + 一个 `@seq.policy` 类)** 一行 `seq deploy` 上到 GS,`connect(model)` 就能 `act` —— 像 Modal 部署一个 GPU 服务那样,但 policy 的 obs→ActionChunk 合同、episode/streaming、warming 由平台内建。**我们不做训练**(只部署已训好的 checkpoint),不拥有 model / sim / 数据。
8
-
9
- 这是更大 thesis(GS = 跑 Real2Sim2Real loop 的 compute+编排引擎)的**入口(on-ramp)**:先把「部署 + 服务一个 policy」(loop 的 Stage 6)做实,再扩到大规模 rollout/eval(Stage 3)。deploy 层是入口,不是终点。
10
-
11
- ## MVP 架构(先做这个):1 worker = 1 VM = 1 L4,on-demand + stop-to-zero
12
-
13
- **最简形状 —— 不养 pool、不做 snapshot。**
14
- - **worker = 一台 GCE L4 VM**(g2-standard-8:8 vCPU / 32GB / 1× L4),跑 harness 容器、装一个 policy。**1 worker = 1 VM = 1 L4 = 1 policy**(pi05 独占显存,一张卡装不下两个 policy)。
15
- - **按 policy(deployment)现起**:有人 connect 而没有在跑的 worker → gateway `driver.create` 起一台(冷启 boot ~1-2min + 加载 86s)。
16
- - **scale-to-zero = 关 VM**:reaper 见 idle 过 cooldown → `driver.stop`(GPU 费归零、保 boot 盘);下次 connect 再 start(GCE GPU VM 不能 suspend,只能 stop/start,吃全 boot)。
17
- - **并行 = 进程级 replica + 加 worker**:一台 worker 内用**进程级 replica(`SubprocessReplica`,非线程)**并发,受 VRAM 限(L4 24GB / pi05 8.6GB ≈ 1~2 个,JAX 关预分配才放得下 2);超了 → 加 VM(每台一张卡),gateway 分流,受 GPU quota + 成本限。
18
- - **存储 3 处**:① 你本地(deploy)② GCS(耐久,checkpoint 永久存 `gs://…`)③ worker 的 **boot disk**(首次 create 从 GCS 拷权重 45s;**boot disk 在 stop 后存活**,gce-1 → 重启免重拉,权重别放会被清的 Local SSD)。
19
-
20
- ## 为什么 GCE 裸 VM(不是 Cloud Run)
21
-
22
- - **gateway 自己控 scale-to-zero**:按闭环 idle 精确关 / 起 worker(见 reaper),不借云商内建 serverless 的黑盒伸缩。
23
- - **direct-connect 要一个可直达的 worker**:机器人 `act` 直连 worker 的公网 IP(绕开 gateway 省 hop);Cloud Run 只给代理在前的 URL,拿不到直连 pod。
24
- - **driver 形状可移植**:`gcloud compute instances create` 起 L4 VM,同形状可复制到 AWS/Azure。
25
- - L4 24GB 装 pi05 宽裕(serving VRAM ~8.6GB)。
26
- - ⚠️ **GCE GPU VM 不能 suspend/resume** —— 只能 stop/start,吃全 OS boot(~1-2min)。但 **boot disk 存活**(gce-1):**首次 create** = boot + 45s 拉权重 + JIT;**start-after-stop** = boot + JIT(权重已在盘,免那 45s)。⚠️ warm 83ms / JIT 34s / cold 86s 是 **RTX 4090** 实测(RS-3),L4 带宽只 ~1/3(300 vs 1010 GB/s)→ L4 大概率更慢,**真机重测再定预算**;MVP 接受冷启,SDK warming-wait 兜底。
27
-
28
- ## 三个 repo 的分工
29
-
30
- | repo | 角色 | 详见 |
31
- |---|---|---|
32
- | **sequence-sdk** | 用户面:`@seq.*` authoring 装饰器 + `Image`/`Volume` 声明 + `seq deploy` CLI + `connect/act` client。copy Modal 的 DX。 | [sdk.md](sdk.md) |
33
- | **sequence-container** | harness runtime:跑在 GCE VM 上的容器,加载用户 policy(或 benchmark)、`/act /ping /health`、GCS 拉权重。 | [container.md](container.md) |
34
- | **sequence-gateway** | control plane / scheduler:`POST /v1/deployments` 注册、`gcp_gce` driver、scheduler(MVP:找 / 起 worker)、fleet state、connect/lease 发直连坐标、gateway 控 scale-to-zero(关 VM)。 | [gateway.md](gateway.md) |
35
- | **sequence-base** | 共享 wire 契约(三方 import,不漂移):`@seq.*` registry、`POST /v1/deployments` payload、`/act` req/resp。 | [contracts.md](contracts.md) |
36
-
37
- 数据流(一次 deploy + 一次 act):
38
- ```
39
- seq deploy → gateway POST /v1/deployments(handler ref + manifest + weights URI + image 声明)
40
- → Cloud Build 出 policy 镜像(harness base + 用户 Handler + deps)
41
- → scheduler:有 running worker? 复用 : driver.create/boot GCE L4 VM 跑 harness
42
- → harness:GCS 拉权重 → @seq.load → serve
43
- connect(model) → gateway /v1/act/connect(一次):scheduler.acquire → ensure worker up
44
- → 返回 { worker_url(static IP), cert 指纹, direct_secret(per-worker Bearer), lease_ttl }
45
- act(obs) [稳态] → worker_url/act 直连(Bearer secret,keepalive)→ ActionChunk ← 无 gateway hop
46
- 直连失败/归零/lease 过期 → SDK 回退 gateway 重 connect(ensure_up: start/boot VM → 新 url+secret)→ 恢复直连
47
- idle → reaper:cooldown 后 stop VM;下次 connect 再 start
48
- ```
49
-
50
- **⚠️ 关键:control plane / data plane 分离(不要每步过 gateway)**。每次 `act` 都过 gateway 会给机器人闭环**每步加一个 gateway hop**,正好抵消 SDK 连接复用省下的握手(~184.9ms)。所以:
51
- - **connect() 经 gateway 一次**(control plane):resolve model → `scheduler.acquire` → ensure worker up → 返回 **worker 直连 URL(static IP)+ cert 指纹 + `SEQ_DIRECT_SECRET`(per-worker、按代数轮换)+ lease**。
52
- - **之后 act() 直连 worker**(data plane):SDK 保一条 kept-alive 连接到 worker,`Bearer direct_secret` 打 worker `/act` —— **gateway 不在热路径**,一跳保温。
53
- - **gateway 仍控 scale-to-zero + 兜底**:worker 归零 / 直连失败 / lease 过期 → SDK 透明回退 gateway 重 acquire(ensure_up:start/boot VM)→ 换新 url+secret → 恢复直连。
54
- - **复用已有件**:harness `transport/auth.py::make_guard(SEQ_DIRECT_SECRET)` 就是这个直连守卫(早期为「pod 公网 IP 上 /act 直连」建的)。
55
- - **这正是 Modal 的做法(不是分野)**:Modal 同一 deployed function 有两条路 —— `.remote()` 走控制面任务队列(~100ms 派发开销),`@modal.fastapi_endpoint` 是容器**直连 web 端点、绕开队列**;机器人走后者。我们 direct-connect = 后者,gateway = Modal 控制面(只在 setup/warming 在路径里)。
56
- - **metering**:gateway 不在热路径 → GPU-秒由 gateway lifecycle 计、request 数由 worker 异步 telemetry(`coldstart.emit` 同模式)上报。
57
-
58
- ## 范围(只做 v1,不过早复杂化)
59
-
60
- - **v1(MVP)**:stock pi05 → 自定义 pi 在 GCE L4 上端到端跑通;**1 worker = 1 VM = 1 L4**;`deploy → provision(GCS 拉权重)→ serve → direct-connect → idle 过 cooldown 关 VM`;冷启:首次 create = boot + 45s 拉权重 + JIT,重启免 45s(boot disk 存活,gce-1);83ms/86s 是 4090 数、待 L4 重测(RS-3);SDK warming-wait 兜底。eval 半边:`eval(policy, benchmark)` 批量并行(见 [eval.md](eval.md))。
61
- - **冷启优化(snapshot / warm pool / weight-cache 等)= 明确不做**,已从本设计删,别过早复杂化;真需要时再从 git 历史捞回。
62
-
63
- ## 非目标 / 边界
64
- - **不做训练**;不拥有 model / sim engine / 用户数据(用户 checkpoint pre-stage 到 GCS,平台不 train、不跨租户复用)。
65
- - **不做 warm pool、不做 snapshot、不做冷启优化**(已从设计删);不做 self-serve 自动镜像 build(先 operator-assisted register)、不做多 region、不做多 provider。
66
- - eval 半边**已开始规划**(见 [eval.md](eval.md)):**benchmark 是第二类可授权 artifact** —— `@seq.benchmark`「create a benchmark」(LIBERO 是例子,对称于 `@seq.policy`/pi05);`eval()` 是 deploy 后可调的**批量并行函数**(与 `act` 服务解耦、无 gate)。spec 分落 sdk/container/gateway/contracts。首个目标 = agentic VLM + pi0.5 在 LIBERO 上测。simulation-as-product / 更大 Real2Sim2Real loop 仍在此设计之外。
@@ -1,86 +0,0 @@
1
- # plan review —— 2026-09-27(8 个 Opus reviewer,4 维 × review+skeptic)
2
-
3
- 四维度 reviewer(correctness / trust-and-money / executability / architecture)各配一个反驳型 skeptic 复核。**28 条发现 → 26 确认、2 驳回**(6 blocker / 15 major / 5 minor)。本文是审计线索 + 修复状态;修复直接改进各 md。
4
-
5
- ## 决策(用户 2026-09-27)
6
-
7
- - **worker 直连 TLS**(blocker F1/TM1/A4):选 **公网 IP + 自签证书 + SDK pin**。worker 保留 static external IP(地址稳定跨 stop/start);harness uvicorn 加载自签 cert;connect 响应下发 cert 指纹;SDK 用自定义 SSLContext pin 该指纹(不走默认 CA)。保住「直连省 hop」。
8
-
9
- ## 状态图例
10
-
11
- > ✅ **两轮的确认修复已全部落到各设计 md**(commit 见 git log;含 START 的 E1–E9、accounts 的 A1 secret 模型 + ⑨ TLS + TM2/5/7、billing 的 F1/F3/TM3/TM4/A6、contracts/README/eval/references/container/gateway/sdk/observability 的外部事实与 TLS/composite 修正)。➖=驳回(不改)。落完做过残留自检(无「一次性 secret」「restore/boot」「:8000」「Spot ÷3」等矛盾)。
12
-
13
- ### Blocker
14
- | id | doc | 一句话 | 状态 |
15
- |---|---|---|---|
16
- | F1 / TM1 / A4 | contracts/container/accounts/gateway/sdk/README | 数据面无 TLS,direct_secret 明文可截获重放;GCE ephemeral IP 会变 | ✅ 公网+自签+pin+static IP |
17
- | E1 | START | 四 repo 无 `integration` 分支,第一个 `worktree add integration` 就 fatal | ✅ runbook 建分支 + build agent fallback |
18
- | E2 | START | 跨 repo 的 goal-diff 完整性闸算不出(goals 在 base、commit 在目标 repo) | ✅ verifier 在 base 仓查 goal diff |
19
- | E3 | START | 每个 WU 强制 USER-TEST,基础件(W0.1/C1/C2/G1/A2)无用户面必 escalate | ✅ USER-TEST 降到里程碑级 + user_task 可选 |
20
- | A1 | accounts | direct_secret per-worker 单值、每 connect 覆盖 → 多机器人互踢 | ✅ 改长寿命 secret、epoch=worker 代数 |
21
-
22
- ### Major
23
- | id | doc | 一句话 | 状态 |
24
- |---|---|---|---|
25
- | E4 | START | BUILD schema 单 commit 装不下跨仓 WU(W0.2/G1/O5) | ✅ commits[] 数组 |
26
- | E5 | START/sdk | `@seq.plan` 只在 C4,SDK 侧无 WU 建装饰器 | ✅ PLAN flag 进 W0.1、装饰器进 S1 |
27
- | E6 | START | O1–O5 没排进 wave 图;「同 wave」违反无 barrier | ✅ 排进 wave 图 |
28
- | E7 | START/billing | real-tier VM 预算 ≤2 单 agent vs 整 run 口径打架 | ✅ 每 WU ≤1 VM、real run 串行 |
29
- | E8 | START | REVIEW reviewer 挂掉 fail-open 放行 | ✅ `(!rv || rv.blocking)` |
30
- | TM2 | accounts/billing | eval `reserved_usd` 余额判定不读 → 并发 eval 穿透超花 | ✅ 预留落成 usage 行 + 缓存同步 |
31
- | TM3 | gateway/billing | `daily_spend_cap` 算瞬时燃烧非当日累计 → churn 绕过 | ✅ 改当日累计 |
32
- | TM4 | billing/gateway | killswitch 删 Cloud Run service、不碰 GCE VM → GPU 照烧 | ✅ 改按标签停 GCE 实例 |
33
- | TM5 | accounts | GPU-秒三处写入无幂等键 → 重复计费 | ✅ record_id=(instance,window) |
34
- | TM7 | accounts | serve 敞口低估,应是 (boot+cooldown)×单价 | ✅ 改敞口不变式 |
35
- | A2 | container/sdk/eval | batched composite 与单例 self.instruction 冲突 | ✅ plan 状态 keyed by env |
36
- | A3 | eval/container | openpi main.py 是 websocket、单 env,不「正好对上 /act」 | ✅ 改「抽 sim 驱动 + 向量化」 |
37
- | A6 | billing/gateway | serve+eval GPU 上限画在 2 卡池、无全局记账 | ✅ 全局 GPU 会计 |
38
- | A7 | container/accounts | pi05 真 checkpoint 可能首-load 联网自取,与「从你桶挂载」冲突 | ✅ 加 provenance 核实 |
39
-
40
- ### Minor
41
- | id | doc | 一句话 | 状态 |
42
- |---|---|---|---|
43
- | F2 | contracts | 端口 8000 应是 8080 | ✅ |
44
- | F3 | accounts | 漏 `/v1/perceive`(代码注释警告过的 stale) | ✅ |
45
- | F4 | references | 还留被删的 snapshot 归零结论、与 v1 矛盾 | ✅ 标为已弃 |
46
- | E9 | START | C5 依赖标成 S5 应是 W0.1 | ✅ |
47
- | A8 | README/gateway | 权重落盘持久性三处互斥 | ✅ 定死放被保留的 boot disk |
48
-
49
- ### 驳回(skeptic 判 real=false,不改)
50
- | id | 为什么不改 |
51
- |---|---|
52
- | TM6 | 脱敏「矛盾」不成立:不变式限的是「不进主进程**环境**/端点」,不是「值绝不进主进程内存」;harness 主进程本就是取 secret 注入子进程的那方,建脱敏表不违反 |
53
- | A5 | reaper idle「只靠异步 usage」不成立:gateway.md 已明写 last_used 由 usage 上报 **+ lease 续租**两条腿刷新 |
54
-
55
- ---
56
-
57
- # 第 2 轮:联网核对外部事实(gs-plan-webcheck,task wuvobw554)
58
-
59
- 4 维(gce-compute / gcp-billing-security / modal / robotics-stack)× reviewer + skeptic(独立**重搜**证伪),每条带 source_url。**11 条 → 7 确认记错(0 blocker / 5 major / 2 minor)、4 驳回;32 条 load-bearing 外部主张验证为对**(Modal DX 映射、GCE suspend/quota/实例身份 JWT/metadata 限额、budget 非硬顶 + Pub/Sub killswitch + detach-billing、Secret Manager 角色、GCS/AR/disk 价、on-demand $0.85 —— 全部核实无误)。
60
-
61
- ### 确认记错(real=true,待改)
62
- | id | doc | plan 记错 | 实际(官方) | 状态 |
63
- |---|---|---|---|---|
64
- | RS-1 | eval/container | openpi `main.py`「正好对上 harness /act」 | 它是 **msgpack-over-websocket**(`WebsocketClientPolicy` → `serve_policy` 的 `WebsocketPolicyServer`),单-env 顺序 loop,非 HTTP REST | ✅ 改「复用 env-loop,把 infer 那步换成进程内 batched policy.act」(= 一轮 A3) |
65
- | RS-2 | eval | 用 `pi05_droid` 跑 LIBERO baseline | LIBERO SOTA 是 **`pi05_libero`** checkpoint(README 96.85 avg);droid 的 LIBERO 数不可比 | ✅ baseline 用 pi05_libero;droid 仅作 wire 占位须标注 |
66
- | RS-3 | references/README | 83ms/34s JIT/86s 当 L4 冷启预算 | 那是 **RTX 4090** 数;L4 带宽 ~1/3(300 vs 1010 GB/s)、FP16 tensor ~73% → L4 warm 大概率数百 ms、JIT 更久 | ✅ 标注 4090 基线、R1/M3 真机重测(= 一轮 improvement) |
67
- | gce-1 | README | 权重「VM 关即失」、start-after-stop 吃全 45s 重拉 | **boot disk 在 stop 后存活**(只 Local SSD 丢);权重放 boot disk → 重启免 GCS 重拉,只 JIT | ✅ 权重落 boot disk;重启建模为 JIT-only(顺带定死 A8) |
68
- | F1 | billing | Spot ≈ on-demand 的 1/3 | L4 spot 只省 ~15%($0.72–0.74 vs $0.85);「91% off」不适用抢手的 L4/G2 | ✅ 改 gpu_rates spot 价 + 删「÷3」措辞 |
69
- | F2 | accounts | `roles/compute.instanceAdmin`(无 .v1) | 预定义角色是 `roles/compute.instanceAdmin.v1`;且 gateway SA 还需 `roles/iam.serviceAccountUser` 才能把 worker SA 附到 VM | ✅ |
70
- | F3 | billing | 成本表漏 external IP | in-use external IPv4 ~$0.005/hr(spot VM ~$0.0025);teardown 随 VM release,别留 reserved 空转 | ✅ 加一行 |
71
-
72
- ### 驳回(real=false / 不构成 plan 错)
73
- | id | 结论 |
74
- |---|---|
75
- | modal-tls-gap | Modal 自带 managed TLS(*.modal.run)属实,但我们**已决**公网+自签+pin 正是为补这个 gap → 非 plan 错,已在 TLS 决策里 own |
76
- | RS-4 | Isaac Sim「几十 GB」不算错:NGC 当前 tag 压缩 9.9GB、解压几十 GB;finding 引的 7GB 是过时值 |
77
- | gce-2 | finding 的 web_says 错了:static IP 挂在**停机**实例上仍算 in-use($0.005/hr),不是它说的 $0.01/hr 更贵档 → 用 F3 的正确版 |
78
- | F4 | killswitch 官方 sample 确实硬编 zone/无 label,但 plan 本就说要「adapt」→ 已被一轮 TM4 覆盖 |
79
-
80
- ## 高价值 improvement(已并入对应修复)
81
- - secret 模型简化(长寿命 per-worker,epoch=worker 代数)→ 解 A1。
82
- - 活性权威归一:reaper 认 `lease_expires_at`,lease 过期先探 `/ping` 再 terminate。
83
- - pi05 的 83ms/86s/290MB/s 是 RunPod-4090/S3 基线,非 L4 → R1/M3 goal 改「量出并记录 L4 数」。
84
- - eval 端点校验 caller 拥有 model+benchmark(403)。
85
- - USER-TEST 前由 workflow 显式拉起 mock 端点。
86
- - dashboard/results-store 补归属 WU 或把 `dashboard_url` 标 optional。
@@ -1,366 +0,0 @@
1
- # START —— 用 Claude Code(workflow + subagent)把平台建出来
2
-
3
- > 本文是**执行计划**:怎么用 Claude Code 的 Workflow 把本文件夹描述的平台(sdk / container / gateway / base 契约 / eval / [accounts](accounts.md) / [billing](billing.md) / [observability](observability.md))真正写出来、验收、交付。**设计**见各 md;本文只管**怎么建**。
4
-
5
- ## 一句话
6
-
7
- 每个 **work unit(WU)** 走同一条流水线:**BUILD**(Opus 实现者写码)→ **VERIFY**(独立 Opus verifier 证明该 WU 的 **goals** 都成立)→ **USER-TEST**(**全新** Opus agent 扮演用户,只拿用户面文档去完成 `user_task`)。**goals 是自然语言写的结果**(例如「pi0.5-DROID 的权重从 volume 正确挂载了」「LIBERO benchmark 正确加载了」),在写码**之前**定稿、实现者不能改;**怎么证明由 verifier 自己决定**。失败回灌实现者、有轮数上限;WU 按**依赖图**分 wave,wave 内并行、wave 间串行 + 人审;真钱(GCP L4)与对外动作(push、prod migration)是人工闸,开发期 GCP 花费有六层硬闸(见 [billing.md](billing.md))。
8
-
9
- ## 原则
10
-
11
- 1. **验事实、不验代理**:测试绿 ≠ 用户能用(memory `verify-the-fact-not-the-proxy`)→ goals 写**结果**、不写测试命令,verifier 必须证明结果本身;再加 USER-TEST,由没看过实现的 agent 当真用户走一遍。
12
- 2. **独立性**:实现者不给自己打分;verifier 在**干净 checkout** 上取证;user-tester **看不到**源码 / diff / 设计 md。
13
- 3. **goals 先于代码、只读**:Stage 0 定稿 commit;verifier 查 goal 文件未改、测试未被削弱。goals 不规定验法 → 实现者没法对着一份已知测试去凑。
14
- 4. **mock tier 先建**(W0.2):没有「假的云」,绝大多数 WU 没法廉价、可重复地验。
15
- 5. **全部 subagent = Opus 5.5**:每个 `agent()` 显式 `model:'opus'` + `effort:'high'`(不继承 session 的 max —— memory 记着继承 max 会让未 pin 的 agent 秒死)。
16
- 6. **按规模分批**:本 session workflow 指引是 < 10 agent/run;每 WU ≈ 4 个 agent → 默认**每 run ≤ 2 个 WU**。想一次跑整 wave,在交互式 `claude` 终端的 `/config` 调「Dynamic workflow size」。
17
- 7. **真钱 / 对外动作人工闸 + 成本硬闸**:真 GCP、push 到 origin、prod Supabase migration 都停下等人批;GCP 开发期花费由 [billing.md](billing.md) 的 L1–L6 兜底。
18
-
19
- ## 流水线阶段
20
-
21
- | # | 阶段 | 谁(全 Opus 5.5) | 输入 | 输出 | 通过条件 |
22
- |---|---|---|---|---|---|
23
- | 0 | **SPEC** | drafter → critic(专挑漏洞)→ finalizer;**人审** | 设计 md + WU 表 | `goals/<id>.yaml`(goals + user_task) | 人批准并 commit |
24
- | 1 | **BUILD** | 实现者(每 WU 一个) | spec 引用 + goals(只读)+ 上轮失败摘要 | `wu/<id>` 分支上的 commit | 本地 test / typecheck / lint 过(自报,不算数) |
25
- | 2 | **VERIFY** | **独立** verifier | build commit + goals | 每条 goal:met / unmet + 证据 | **全部 met** 且 goal 文件未改 且 测试未削弱 |
26
- | 3 | **USER-TEST** | **全新** agent 扮演用户 | 装好的包 + 用户文档 + mock 端点 + `user_task` | completed / blocker / friction / evidence | `completed = true`(friction 进 backlog) |
27
- | 4 | **FIX 回路** | 回到 BUILD | 2 或 3 的失败摘要(不是整份 transcript) | 新 commit | ≤ 2 轮;超了 escalate 给人 |
28
- | 5 | **REVIEW** | 对抗式 reviewer(`feature-dev:code-reviewer`) | 过了 3 的 commit | findings / blocking | 无 blocking |
29
- | 6 | **INTEGRATE**(里程碑) | 全新 agent 当用户走 E2E | 已合进 `integration` 的多个 WU | 同 USER-TEST | 里程碑 `user_task` 完成 |
30
- | 7 | **SHIP** | 人 + 主 loop | 通过的 wave / 里程碑 | push、prod migration | 人批准 |
31
-
32
- **VERIFY vs USER-TEST**:两者都用自然语言,但视角不同。VERIFY 是**工程师视角、白盒** —— 能看一切(代码、日志、DB),要证明 goals 为真;USER-TEST 是**用户视角、黑盒** —— 只看用户材料,要把事办成。前者抓「没做到」,后者抓「做到了但用不了」(文档缺步、隐含前提、实现者上下文泄漏)。两者都要过。
33
-
34
- ## goals 格式(每 WU 一个 `docs/platform/goals/<id>.yaml`)
35
-
36
- ```yaml
37
- id: C2
38
- repo: sequence-container
39
- depends_on: [C1]
40
- tier: mock # mock | real(real = 烧钱,过人工闸)
41
- spec: [container.md#worker-bootstrap, accounts.md#⑥-worker-bootstrap]
42
- goals: # 自然语言的结果:做完后世界上哪些事是真的;怎么证明由 verifier 决定
43
- - pi0.5-DROID 的权重从 volume 正确挂载进 worker(文件齐全、与源一致,不是空目录、也不是现场重下)
44
- - pi0.5-DROID 能被成功调用:给它一帧 DROID 观测,它返回一个合法的 ActionChunk
45
- - worker 开机后自己领到了 direct_secret;不带这个 secret 的 /act 调用会被拒
46
- - 用户的 HF token 进了 policy 进程,且没有出现在任何日志里
47
- user_task: # Stage 3:只有这段给 user-tester
48
- persona: "机器人工程师,没见过 GS 内部,只有 SDK README 和一个 test API key"
49
- task: "把 stub policy 部署上去,调一次 act 拿到动作"
50
- success: "拿到一个 action chunk"
51
- ```
52
-
53
- 再比如 benchmark 侧的 goals:「LIBERO benchmark 正确加载:5 个 suite 的任务都能列出,任选一个任务能 reset 出第一帧观测」「adapter 把 LIBERO 观测转成 pi05 要的格式,并如实标出哪些转换有损」。
54
-
55
- - **每条 goal 是结果**(做完后什么是真的),不是步骤、也不是测试命令。
56
- - **用人话,但要能判真假**:「pi05 能用」太虚 ✗;「给一帧 DROID 观测,返回合法 ActionChunk」✓。Stage 0 的 critic 专门挑太虚、证伪不了的 goal。
57
- - **不规定怎么验**:verifier 针对每条 goal **自己设计取证**(读代码、跑命令、调端点、查日志 / DB / 文件),逐条给 met / unmet + 证据;证据不足 = unmet;实现者的自述不算证据。
58
- - 脚本没有文件系统:主 loop 读 YAML、解析后经 `args` 传入;user-test prompt **只拼 `user_task` 段**。
59
-
60
- ## USER-TEST(clean user agent)
61
-
62
- - **给它**:persona / task / success;全新 venv(从该 WU 的 commit `pip install`,建在 [`sequence-testing`](https://github.com/General-Sequences/sequence-testing) 里 —— 那个仓只装 SDK、不含 GS 源码,天然隔离);用户面文档(SDK README、`seq --help`、quickstart、模板);mock 端点 + test API key。
63
- - **不给**:源码、diff、实现者 transcript、`docs/platform/` 设计 md、goal 文件的 `goals` 段。
64
- - **必须回**:`completed`、`blocker`、`friction[]`(每个卡住 / 困惑 / 文档缺口)、`evidence[]`(命令 + 输出)。**friction 即使 completed 也收**。
65
- - **诚实局限**:subagent 有读文件能力,「不看源码」靠 prompt + 证据要求 + reviewer 抽查约束,不是硬隔离;发现 tester 引用了源码,该轮作废重跑。
66
-
67
- ## 测试层级:mock vs real
68
-
69
- | | mock tier(默认,每轮都跑) | real tier(里程碑,人工闸) |
70
- |---|---|---|
71
- | driver | `MockDriver`:worker = 本机 CPU harness 进程 | `gcp_gce`:真 L4 VM(dev 项目 `gs-dev`) |
72
- | policy | stub policy(固定 ActionChunk,无 GPU) | 真 pi05(JAX/openpi on L4) |
73
- | benchmark | stub benchmark(1 维 reach env,无 sim 依赖) | LIBERO(MuJoCo image + EGL) |
74
- | Supabase | `supabase start` 本地 + 全部 migrations | 线上项目(只在 SHIP 动 schema) |
75
- | GCS / Secret Manager / 实例身份 | 本地目录 / 内存假 SM / 本地签发的假 JWT | 真 GCS / 真 Secret Manager / 真 GCE identity token |
76
- | 成本 | 0 | 受 [billing.md](billing.md) L1–L6 约束,月上限 ≈ $141 |
77
-
78
- ## Work units(v1)
79
-
80
- | WU | 白话:做什么 → 为了什么 | 关键件 | repo | 依赖 | tier |
81
- |---|---|---|---|---|---|
82
- | **W0.1** | 先把各仓之间「说话的格式」定死(policy 怎么描述、connect 回什么、eval 报告长什么样)→ 为了 sdk / container / gateway 能各自并行写、最后拼得上 | wire 类型 + JSON schema(含 `SeqFlags.PLAN`,给 composite 用)| sequence-base | — | unit |
83
- | **W0.2** | 搭一个「假的云」:假 GPU 机器(本机进程)、本地数据库、假存储 / 假身份、假模型、假 benchmark → 为了不花钱、不等真 GPU 就能反复测每一块 | MockDriver、stub policy / benchmark | 跨仓 | W0.1 | mock |
84
- | **S1** | 让用户用 `@seq.policy` + `@seq.load / infer`(+ composite 的 `@seq.plan`)写出一个 policy 类 → 为了用户只写模型逻辑、composite 的规划钩子也能声明(E5) | 装饰器(含 `@seq.plan`)+ registry | sequence-sdk | W0.1 | mock |
85
- | **S2** | 让用户用代码声明要装什么包、权重放哪 → 为了平台能替用户 build 镜像、挂权重 | `seq.Image` / `seq.Volume` | sequence-sdk | S1 | mock |
86
- | **A3** | 让用户存自己的私密 key(如 HF token、**自己的 OpenRouter key**),一个名字存一组 env,policy 里只写名字 → 为了私有权重、composite 里**用户自带的 VLM** 能用,但值永不进代码、日志和轨迹 | `seq.Secret`(env 组) | sequence-sdk | S1 | mock |
87
- | **S5** | 让用户像写 policy 一样写 benchmark、接好 sim 与 policy、一行发起测评,**并指定用几张 GPU 跑**(`gpus=N`,先 `dry_run` 看耗时和花费)→ 为了「create a benchmark」和「create a policy」一样简单、测评想快就加卡;LIBERO 只是一个例子 | `@seq.benchmark` / `@seq.adapter` / `seq.eval` | sequence-sdk | S1 | mock |
88
- | **S3** | 一条命令把写好的 policy 注册到平台 → 为了从写完代码到上线只差一步 | `seq deploy` | sequence-sdk | S1, S2, A3 | mock |
89
- | **S4** | SDK 先问 gateway 要 worker 地址和 secret,之后直接连 worker → 为了每一步 act 省掉 gateway 那一跳的延迟 | direct-connect client | sequence-sdk | W0.1;E2E 需 G4、C3 | mock |
90
- | **S6** | 一键生成可改的范例(`seq init pi05-droid` / `seq init benchmark libero`)→ 为了用户从范例改起,不用从零读文档 | 模板 | sequence-sdk | S3, S5, R1, R2 | real |
91
- | **C1** | 容器能读懂用户的 `@seq.policy` 类并对外提供 `/act` → 为了任何用户 policy 都能跑在同一个 harness 里 | registry loader | sequence-container | W0.1 | mock |
92
- | **C2** | GPU 机器开机后自己向 gateway 领 secret、从 GCS 拉权重 → 为了 secret 不经过机器元数据、权重自动就位 | bootstrap + GCS fetch | sequence-container | C1 | mock |
93
- | **C3** | 只接受带正确 secret 的请求,并把用量报给 gateway → 为了直连也安全、gateway 不在路径上也能计费 | `/act` 守卫 + usage 上报 | sequence-container | C1 | mock |
94
- | **C4** | 一个 policy 里「VLM 做规划、pi05 出动作」:**VLM 用用户自己的 OpenRouter key**(只注入 policy 子进程、日志脱敏),低频规划、不挡每步 act → 为了 demo 要测的 agentic VLM + pi05 能跑,又不把网络延迟塞进控制环、不替用户付 VLM 的钱(mock 里用假 VLM) | composite policy **runtime**(`@seq.plan` 授权在 S1/W0.1) | sequence-container | C1, S1 | mock → real |
95
- | **C5** | 一台机器同时跑很多个仿真环境、把观测攒成一批一起送进 policy;每卡跑几个 env 按机型自动定,从队列领活 → 为了 eval 跑得快、GPU 喂得满、慢 episode 不拖整体 | benchmark 运行时 | sequence-container | C1, W0.1(契约 5) | mock |
96
- | **G1** | 在 Supabase 加存部署、benchmark、eval 结果、secret 元数据、worker 状态、费率的表 → 为了平台所有状态有地方记、可查、可审计 | migrations + `state.py` | gateway + `general-app/supabase` | W0.2 | mock |
97
- | **G2** | gateway 能在 GCP 上建 / 停 / 查一台 L4 GPU 机器 → 为了平台能按需开关 GPU | `gcp_gce` driver | sequence-gateway | W0.1 | mock |
98
- | **G3** | 有人要用时找一台或新开一台,闲了自动关 → 为了有人用才花钱、没人用归零 | scheduler + reaper | sequence-gateway | G1 | mock |
99
- | **A1** | 把「余额不够就拒」挪到 connect、按 GPU 秒记账、成本改成 GCP 的价、成本上限生效 → 为了直连之后照样收得到钱、算得清利润、不超支 | 计费扩展 + L4 上限 | sequence-gateway | G1 | mock |
100
- | **A2** | gateway 发一次性直连 secret(库里只存 hash)、验证开机机器的身份、存用户 secret → 为了 secret 从生成到使用全程不外泄 | secret 签发 + bootstrap 端点 | sequence-gateway | G1 | mock |
101
- | **G4** | 把部署、connect、开机领 secret、上报用量、存 secret 这些接成 HTTP 接口 → 为了上面各块变成用户能调的服务 | routes | sequence-gateway | G1, G3, A1, A2 | mock |
102
- | **G5** | 一次 eval **按用户指定的 GPU 数**起机器(受 `max_gpus_per_eval` 和配额约束,被截断会明说),先预留费用,worker 从 shard 队列领活并行跑、挂了或被抢占自动重派,最后汇总并按实际结算 → 为了测评想快就加卡,又不超支 | eval fan-out + shard 队列 | sequence-gateway | G3, G4, A1 | mock |
103
- | **R1** | pi05 在真 L4 上跑起来、延迟达标 → 为了证明 mock 里通的东西在真 GPU 上也通 | pi05 镜像 | sequence-container | C1, C2 | **real** |
104
- | **R2** | LIBERO 仿真镜像 + LIBERO benchmark + 接 pi05 的 adapter,在无显示器的机器上跑完一个 episode → 为了拿到 pi05 在 LIBERO 上的真实成功率 | LIBERO 镜像 + adapter | sequence-container | C5, S5 | **real** |
105
- | **R3** | 驱动在真云上建一台、停一台 L4 → 为了确认开关 GPU 这条链路在真 GCP 上可靠(带成本硬闸) | 真 GCP | sequence-gateway | G2 | **real** |
106
- | **O1** | SDK 每请求铸 rid + 掐 total/rtt/network + 异步批量上报;修 warming 判断 → 为了直连后客户端这侧能被观测、冷启能等 | sequence-sdk | S4, W0.1 | mock |
107
- | **O2** | harness 回 `perf`、打带 rid 的每请求日志、按窗口上报 usage+latency、脱敏过滤器、`/diag` → 为了 worker 这侧能被观测、secret 不外泄 | sequence-container | C1, C3 | mock |
108
- | **O3** | gateway ingest(收 SDK/worker 上报写 `request_latency`/`usage`)+ 复用 `latency_percentiles` / `/v1/admin/*` + usage wire 加 latency 字段 → 为了聚合与查询 | sequence-gateway | G1, G4 | mock |
109
- | **O4** | cold-start telemetry 在 GCE 上跑通:worker 身份改 JWT、接线 `entrypoint`、补 stage 词表 + 时间戳 + rid → 为了冷启可观测 | sequence-container | C2 | mock → real |
110
- | **O5** | debug 工具:`seq logs` / `seq doctor` 扩到直连、`inspect/contract.py` 更新路径、里程碑 latency/cost 图脚本 → 为了能排障、出 demo 图 | 跨仓 | O1, O2, O3 | mock |
111
-
112
- 技术细节在各设计 md(observability 相关见 [observability.md](observability.md));每个 WU 的 goal 文件用 `spec:` 指到具体章节。**O1–O5 的排期(紧随各自上游的**下一** wave —— 放同 wave 会违反无 barrier,E6)**:O2 在 C3 后(Wave 3)、O4 在 C2 后(Wave 3)、O1 在 S4 后(Wave 4)、O3 在 G4 后(Wave 4)、O5 收尾(Wave 4')。
113
-
114
- ## 依赖图 & 并行关系
115
-
116
- - **同一 WU 内**:BUILD → VERIFY → USER-TEST → REVIEW 严格先后。
117
- - **同一 wave 内的不同 WU**:互不依赖,**全并行**(`pipeline()` 无 barrier —— A 在 USER-TEST 时 B 可以还在 BUILD)。
118
- - **wave 之间**:串行 —— 上一 wave 的 pass 分支合进各 repo 的 `integration`、人看完报告,下一 wave 才从 `integration` 开工。
119
- - **Stage 0 的 goals**:全部 WU 可**一次并行**写完(goals 由 spec 推出,不依赖代码;物理上按 run 上限分批)。
120
-
121
- ```
122
- Stage 0 SPEC:全部 WU 的 goals 并行起草 → 挑漏洞 → 定稿 → 人审 → 记每个 goal 的 sha256 → commit
123
- │ ⟵ 跑第一个 build wave 前:对每个目标 repo `git -C <repo> branch integration main`(E1)
124
- Wave 0 W0.1 contracts ──→ W0.2 mock tier (严格先后)
125
- │
126
- Wave 1 S1 ║ C1 ║ G1 ║ G2 (只依赖 wave 0)
127
- │
128
- Wave 2 S2 ║ A3 ║ S5 ║ C2 ║ C3 ║ C4 ║ C5 ║ A1 ║ A2 ║ G3 (上游全在 wave 1)
129
- │
130
- Wave 3 G4 ║ S3 ║ O2 ║ O4 (G4←G1,G3,A1,A2;S3←S1,S2,A3;O2←C3;O4←C2)
131
- Wave 3' S4 ║ O1? (S4 E2E 需 G4+C3;O1←S4 → 实际 O1 落 Wave 4)
132
- │
133
- ═══ M1 mock E2E:seq deploy → connect → act(第二次绕开 gateway)→ ledger 记账;零余额 → 402
134
- │
135
- Wave 4 G5 ║ O1 ║ O3 (G5←G3,G4,A1;O1←S4;O3←G4)
136
- │
137
- ═══ M2 mock E2E:eval stub policy × stub benchmark → report;余额先预留后结算
138
- │
139
- Wave 4' O5 (←O1,O2,O3)
140
- │
141
- ⛔ 人工闸:real tier —— billing.md L1–L6 已就位(gs-dev、L4 配额 2、$100 killswitch **停 GCE 实例**、孤儿清扫),你说 go
142
- │
143
- Wave 5 R3 → R1 → R2 (串行!每个是独立 real run、≤1 VM、自带 teardown —— L4 配额 2 撑不住并行 3 个,E7)
144
- │
145
- ═══ M3 real:从零 deploy stock pi05 → act → idle 关 VM → GPU-秒入账
146
- ═══ M4 real:pi05(**pi05_libero** checkpoint,RS-2)在 LIBERO libero_spatial(小 N)出成功率
147
- │
148
- Wave 6 S6 ║ C4-real
149
- ═══ M5 real:agentic VLM + pi05 vs pi05 单独,libero_10(demo)
150
- ═══ M6 人:真机 SO-101 抓取(money shot)
151
- │
152
- SHIP(人工闸):push 各 repo main;prod Supabase migration 由主 loop 直接 apply 并对 live 验证
153
- ```
154
-
155
- **关键路径**:W0.1 → W0.2 → G1 → (A1 ∥ A2 ∥ G3) → G4 → S4 → **M1** → G5 → **M2** → ⛔ → (R1 ∥ R3) → **M3** → **M4** → **M5**。压工期就盯这条;S2 / A3 / S5 / C4 / C5 不在关键路径上,排晚也不卡。
156
-
157
- ## 里程碑(INTEGRATE,clean-user E2E)
158
-
159
- 里程碑都在 **[`sequence-testing`](https://github.com/General-Sequences/sequence-testing)** 里跑(`~/dev/general-seq-prod/sequence-testing`):每个里程碑一个目录,`milestones/<id>/README.md` 是它的规格(user_task、自然语言 goals、要出的产物、tier 与成本闸),场景脚本随实现补上。产物(**mp4 录像**、延迟 / 成本图、报告)写到 `runs/<milestone>/<run_id>/`,不进 git;要留档或做 demo 的上传 GCS,结论写进 `reports/`。
160
-
161
- | 里程碑 | tier | `user_task`(给全新 Opus 用户 agent) | 成功标准 |
162
- |---|---|---|---|
163
- | **M1** | mock | 「装 SDK,写一个 stub policy,`seq deploy`,connect,act 10 次」 | 10 个 ActionChunk;gateway 只见 1 次 connect;ledger 有 usage;零余额 key connect → 402 |
164
- | **M2** | mock | 「对刚才的 policy 跑 stub benchmark 的 eval」 | 拿到 report(per-task SR);余额先预留、跑完按实际结算 |
165
- | **M3** | real | 「从零把 stock pi05 部署到 GS 并在脚本里 act」 | 真 L4 起来、act 通、idle 后 VM stopped、GPU-秒入账 |
166
- | **M4** | real | 「在 LIBERO libero_spatial 上 eval pi05(小 N)」 | 出成功率;**每个 episode 一段 mp4**;adapter 的有损项写进 report |
167
- | **M5** | real | 「agentic VLM(用户自带 OpenRouter key)+ pi05 vs pi05,libero_10」 | 两个 SR 可比 + **同任务并排 mp4**(demo 素材);key 不出现在任何日志 / 轨迹里 |
168
- | **M6** | 人 | 真机 SO-101 调 API 抓东西 | latency / cost 图 |
169
-
170
- ## real tier 的成本硬闸(开发流程这一层 = billing.md 的 L6)
171
-
172
- - **你说 go 才跑**;只在 dev 项目 `gs-dev` 里建资源。
173
- - **每次 real run**:≤ 2 台 VM、≤ 60 分钟、用 Spot(测真实延迟的 M3 除外)。
174
- - **所有资源打标签** `gs-env=dev` + `gs-run=<run_id>`。
175
- - **run 结束必跑 teardown agent**:停掉并删除该 `run_id` 的全部实例,前后各列一次,**确认剩 0 台**;teardown 失败 → 立刻告诉你。
176
- - 底下还有兜底:L2 L4 配额 = 2(GCP 硬拒)、L3 $100 killswitch、L5 每 15 分钟孤儿清扫(见 [billing.md](billing.md))。
177
-
178
- ## workflow 骨架(按 workflow-authoring 的真实 API)
179
-
180
- ### Stage 0:`gs-spec-goals`
181
-
182
- ```js
183
- export const meta = {
184
- name: 'gs-spec-goals',
185
- description: 'Draft, adversarially harden, and write natural-language goal files for GS work units',
186
- phases: [
187
- { title: 'Draft', detail: 'opus drafts outcome goals + user_task per WU from the design docs' },
188
- { title: 'Critique', detail: 'opus hunts for vague, unfalsifiable, or gameable goals' },
189
- { title: 'Finalize', detail: 'opus closes the holes and writes goals/<id>.yaml' },
190
- ],
191
- }
192
- // args: { wus: [{ id, repo, depends_on, tier, spec }] }
193
- const OPUS = { model: 'opus', effort: 'high' }
194
- const GOAL = { type: 'object', required: ['id', 'goals', 'user_task'], properties: {
195
- id: { type: 'string' },
196
- goals: { type: 'array', items: { type: 'string' } },
197
- user_task: { type: 'object', required: ['persona', 'task', 'success'], properties: {
198
- persona: { type: 'string' }, task: { type: 'string' }, success: { type: 'string' } } } } }
199
- const HOLES = { type: 'object', required: ['holes'],
200
- properties: { holes: { type: 'array', items: { type: 'string' } } } }
201
-
202
- return await pipeline(args.wus,
203
- wu => agent(`Draft the goals for ${wu.id} (${wu.repo}) from ${wu.spec.join(', ')} under docs/platform/. ` +
204
- `Goals are natural-language OUTCOMES that must be true when the unit is done, e.g. ` +
205
- `"pi0.5-DROID weights are mounted correctly from the volume" or "the LIBERO benchmark loads correctly". ` +
206
- `Each goal: an outcome, not a step or a test command; falsifiable by an observer; no prescribed way to verify. ` +
207
- `Also write a user_task: a user-language task with an observable success, revealing nothing about the implementation.`,
208
- { ...OPUS, schema: GOAL, phase: 'Draft', label: `draft:${wu.id}` }),
209
- async (g, wu) => g && ({ g, crit: await agent(
210
- `Critique these goals for ${wu.id}. For each: is it an outcome rather than a step or test? Could an observer tell ` +
211
- `true from false? Is it so vague that a trivial check would pass it? What in the spec is not covered? ` +
212
- `Could a wrong or lazy implementation make every goal true?\n${JSON.stringify(g)}`,
213
- { ...OPUS, schema: HOLES, phase: 'Critique', label: `critique:${wu.id}` }) }),
214
- (x, wu) => x && agent(`Rewrite the goals for ${wu.id} closing these holes, keeping them natural-language outcomes, ` +
215
- `then write docs/platform/goals/${wu.id}.yaml (do not commit).\n` +
216
- `Goals: ${JSON.stringify(x.g)}\nHoles: ${JSON.stringify(x.crit ? x.crit.holes : [])}`,
217
- { ...OPUS, schema: GOAL, phase: 'Finalize', label: `finalize:${wu.id}` }))
218
- ```
219
-
220
- ### Stage 1–5:`gs-build-wave`(每批 WU 跑一次)
221
-
222
- ```js
223
- export const meta = {
224
- name: 'gs-build-wave',
225
- description: 'Build a batch of GS work units: build, verify goals, clean-user test, review, real-tier teardown',
226
- phases: [
227
- { title: 'Build', detail: 'opus implementer per WU on its own wu/<id> worktree' },
228
- { title: 'Verify', detail: 'independent opus verifier proves each natural-language goal on a clean checkout' },
229
- { title: 'UserTest', detail: 'fresh opus agent acting as a user, user-facing docs only' },
230
- { title: 'Review', detail: 'opus adversarial code review of passed units' },
231
- { title: 'Teardown', detail: 'real tier only: delete every VM of this run and confirm zero remain' },
232
- ],
233
- }
234
- // args: { tier:'mock'|'real', run_id, maxRounds:2, goal_repo:'/abs/…/sequence-base',
235
- // repo_roots:{'sequence-container':'/abs/…','sequence-gateway':'/abs/…',…}, // 每 repo 绝对路径
236
- // wave: [{ id, repos:['sequence-sdk',…], goal_file, goal_sha256, spec, user_docs, user_task? }] } // user_task 可选(E3)
237
- const OPUS = { effort: 'high' } // 继承 session 模型(Opus 4.8);Opus 5.5 会触发 reasoning_extraction 安全机制
238
- const BUILD = { type: 'object', required: ['commits', 'summary'], properties: { // E4:跨仓 WU 可回多个 commit
239
- commits: { type: 'array', items: { type: 'object', required: ['repo', 'branch', 'commit'], properties: {
240
- repo: { type: 'string' }, branch: { type: 'string' }, commit: { type: 'string' } } } },
241
- summary: { type: 'string' }, tests_run: { type: 'string' } } }
242
- const VERDICT = { type: 'object', required: ['goals', 'goal_intact', 'tests_not_weakened'], properties: {
243
- goals: { type: 'array', items: { type: 'object', required: ['goal', 'met', 'evidence'], properties: {
244
- goal: { type: 'string' }, met: { type: 'boolean' },
245
- evidence: { type: 'array', items: { type: 'string' } } } } },
246
- goal_intact: { type: 'boolean' }, // E2:goal 文件 sha256 == Stage-0(在 base 仓核,不跨 repo diff)
247
- tests_not_weakened: { type: 'boolean' } } }
248
- const USERTEST = { type: 'object', required: ['completed', 'friction', 'evidence'], properties: {
249
- completed: { type: 'boolean' }, blocker: { type: 'string' },
250
- friction: { type: 'array', items: { type: 'string' } },
251
- evidence: { type: 'array', items: { type: 'string' } } } }
252
- const REVIEW = { type: 'object', required: ['blocking', 'findings'], properties: {
253
- blocking: { type: 'boolean' }, findings: { type: 'array', items: { type: 'string' } } } }
254
- const TEARDOWN = { type: 'object', required: ['remaining_instances', 'deleted'], properties: {
255
- remaining_instances: { type: 'number' }, deleted: { type: 'array', items: { type: 'string' } } } }
256
-
257
- const gcpRule = args.tier === 'real' // E7:每个 real run 单 WU、≤1 VM(给 L4 配额=2 留一台余量做重试/孤儿)
258
- ? ` REAL TIER: GCP project gs-dev only; label every resource gs-env=dev,gs-run=${args.run_id}; ` +
259
- `at most 1 VM for this WU and never exceed the run budget of 1 VM; Spot unless the goal is latency; never exceed 60 minutes.`
260
- : ' Do NOT touch real GCP.'
261
- const buildPrompt = (wu, fb) =>
262
- `Implement ${wu.id}. Spec: ${wu.spec.join(', ')}. Goals (READ-ONLY): ${args.goal_repo}/${wu.goal_file}. ` +
263
- `Target repo(s), absolute: ${wu.repos.map(r => `${r}=${args.repo_roots[r]}`).join(', ')}. ` +
264
- `In EACH target repo first ensure the integration branch exists ` + // E1:四仓现在只有 main
265
- `(\`git -C <root> rev-parse --verify integration || git -C <root> branch integration main\`), ` +
266
- `then \`git -C <root> worktree add <root>/../wt/${wu.id} -b wu/${wu.id} integration\` and work there (no cd). ` +
267
- `Run each repo's build/test/lint and paste output. Commit per the CLAUDE.md Git rules ` +
268
- `(user identity, no Claude attribution). Do NOT push. Do NOT edit the goal file. Path-scoped commits only in general-app. ` +
269
- `Return one {repo,branch,commit} per repo you changed.` + gcpRule + // E4:commits[]
270
- (fb ? `\nPrevious round failed:\n${fb}` : '')
271
- const verifyPrompt = (wu, b) =>
272
- `You are an independent verifier; you did not write these commits: ${b.commits.map(c => `${c.repo}@${c.commit}`).join(', ')}. ` +
273
- `Check each out in a fresh worktree under its repo root in ${JSON.stringify(args.repo_roots)}. ` +
274
- `For EACH goal in ${args.goal_repo}/${wu.goal_file} (natural language), decide yourself how to establish whether it is true: ` +
275
- `read code, run commands, call endpoints, inspect logs/DB/files. The implementer's summary is not evidence. ` +
276
- `Report met/unmet per goal with concrete evidence; if you cannot establish a goal, it is unmet. ` +
277
- `goal_intact = \`sha256sum ${args.goal_repo}/${wu.goal_file}\` equals the Stage-0 hash ${wu.goal_sha256} ` + // E2:base 仓核 hash,不跨 repo diff
278
- `(the goal lives in sequence-base, not the build repo). ` +
279
- `tests_not_weakened = no test deleted, skipped, or loosened vs integration in each repo.` + gcpRule
280
- const userTestPrompt = (wu, b) =>
281
- `You are a user: ${wu.user_task.persona}. You have ONLY a fresh venv with the package installed from ${b.commit}, ` +
282
- `the user docs at ${wu.user_docs}, and the mock endpoints + test API key in the environment. ` +
283
- `Do NOT read source code, diffs, or docs/platform/. Task: ${wu.user_task.task}. Success looks like: ${wu.user_task.success}. ` +
284
- `Report every confusing step or doc gap as friction, even if you succeed; evidence = commands you ran + their output.`
285
- const reviewPrompt = r =>
286
- `Adversarially review ${r.b.commits.map(c => `${c.repo}@${c.commit}`).join(', ')} (WU ${r.id}): secret leakage, injection, ` +
287
- `authz gaps, contract drift vs sequence-base, cost-cap bypass, over-engineering. blocking=true only for real defects.`
288
- const teardownPrompt = id =>
289
- `In GCP project gs-dev, list every Compute Engine instance labeled gs-run=${id} ACROSS ALL ZONES, stop and delete them all, ` +
290
- `release any static IP reserved for this run, then list again. remaining_instances is the count after deletion; it must be 0.`
291
-
292
- async function runUnit(wu) {
293
- let fb = ''
294
- for (let round = 0; round <= args.maxRounds; round++) {
295
- const b = await agent(buildPrompt(wu, fb), { ...OPUS, schema: BUILD, phase: 'Build', label: `build:${wu.id}#${round}` })
296
- if (!b) return { id: wu.id, status: 'escalate', why: 'builder died' }
297
- const v = await agent(verifyPrompt(wu, b), { ...OPUS, schema: VERDICT, phase: 'Verify', label: `verify:${wu.id}#${round}` })
298
- if (!v) return { id: wu.id, status: 'escalate', why: 'verifier died', b }
299
- if (!v.goal_intact || !v.tests_not_weakened)
300
- return { id: wu.id, status: 'escalate', why: 'goals or tests tampered', b, v } // 挪球门 → 直接上报人
301
- const unmet = v.goals.filter(g => !g.met)
302
- if (unmet.length) {
303
- fb = 'GOALS NOT MET:\n' + unmet.map(g => `- ${g.goal}\n evidence: ${g.evidence.join('; ')}`).join('\n')
304
- continue
305
- }
306
- if (!wu.user_task) return { id: wu.id, status: 'pass', b, v } // E3:基础件无用户面 → 跳过 USER-TEST(clean-user 只在里程碑)
307
- const u = await agent(userTestPrompt(wu, b), { ...OPUS, schema: USERTEST, phase: 'UserTest', label: `usertest:${wu.id}#${round}` })
308
- if (u && u.completed) return { id: wu.id, status: 'pass', b, v, u }
309
- fb = 'USER TEST FAILED:\n' + (u ? `${u.blocker || ''}\n${u.friction.join('\n')}` : 'tester died')
310
- }
311
- return { id: wu.id, status: 'escalate', why: 'max rounds', fb }
312
- }
313
-
314
- async function review(r) {
315
- if (!r || r.status !== 'pass') return r
316
- const rv = await agent(reviewPrompt(r), { ...OPUS, schema: REVIEW, phase: 'Review', label: `review:${r.id}`,
317
- agentType: 'feature-dev:code-reviewer' }) // 若此 agentType 未注册,删本行退回默认 workflow subagent
318
- return { ...r, review: rv, status: (!rv || rv.blocking) ? 'escalate' : 'pass' } // E8:reviewer 挂掉 = escalate,不 fail-open
319
- }
320
-
321
- const results = await pipeline(args.wave, runUnit, review) // WU 之间无 barrier
322
- if (args.tier !== 'real') return { results }
323
- const teardown = await agent(teardownPrompt(args.run_id), // real tier:无论成败都收尾
324
- { ...OPUS, schema: TEARDOWN, phase: 'Teardown', label: `teardown:${args.run_id}` })
325
- return { results, teardown }
326
- ```
327
-
328
- **骨架要点**
329
- - `agent()` 用 `effort:'high'`、**不 pin model**(继承 session 的 Opus 4.8;Opus 5.5 会撞 `reasoning_extraction` 安全机制 —— 第一轮 review 就是这么 4 个 agent 全挂的)。
330
- - `pipeline(args.wave, runUnit, review)`:WU 之间无 barrier;FIX 回路是 `runUnit` 里的普通 `for`。
331
- - **跨 repo(E4)**:一个 WU 可能改多个 repo → BUILD 回 `commits[{repo,branch,commit}]`;build/verify agent 用**绝对路径** `git -C <root> …`(`isolation:'worktree'` 只隔离 session 所在 repo,不够)。repo 绝对路径经 `args.repo_roots` 传入。
332
- - **goal 完整性(E2)**:goal 住 sequence-base、build commit 在别的 repo,跨 repo `git diff` 算不出 → verifier 改核 `sha256sum goal_file == args 传入的 Stage-0 hash`。
333
- - **USER-TEST 只对有 `user_task` 的 WU(E3)**:基础件(W0.1/C1/C2/G1/A2…)跳过;真正的 clean-user E2E 在里程碑(sequence-testing)。
334
- - **real tier(E7)**:每个 real run 单 WU、≤1 VM;teardown 在 pipeline 后无条件跑,`remaining_instances ≠ 0` 或 teardown 死掉 → 立刻上报你并手动清。
335
- - **REVIEW 不 fail-open(E8)**:reviewer 挂掉 = escalate。
336
- - 脚本**无文件系统**、不能用 `Date.now()` / `Math.random()`:goal YAML、`goal_sha256`、`run_id`、`repo_roots` 都经 `args` 传入。
337
- - 断点续跑:`Workflow({ scriptPath, resumeFromRunId })`,未改的前缀 agent 调用命中缓存。
338
- - `escalate` 的 WU 不自动重试到死 —— 返回主 loop,我带失败摘要汇报给你。
339
-
340
- ## subagent 规则
341
-
342
- CLAUDE.md 会自动注入每个 workflow subagent(输出格式、证据 `{}`、代码与 Git 规则),**不贴进 prompt**;prompt 里只点名本阶段要用的:
343
- - **BUILD**:commit 用用户身份、**不带任何 Claude attribution**、**不 push**、改完跑 build/test 贴输出;real tier 只在 `gs-dev`、打标签、≤ 2 VM、≤ 60 分钟。`general-app` 工作区里有**绝不能提交**的 `frontend/investor_*`、`frontend/tools/*lab.html`、`*preview.html` → 只许 path-scoped 提交。不往 `sequences-models` 写(共享 checkout,只读复用)。
344
- - **VERIFY**:每条 goal 自己取证、证据不足判 unmet;查 goal / 测试未被动过。
345
- - **USER-TEST**:只用给定材料、不读源码、friction 全报。
346
- - **REVIEW**:secret 泄漏、注入、越权、契约漂移、**绕过成本上限**、过度设计。
347
- - 全部用 schema 结构化输出。
348
-
349
- ## 人工闸 & 成本
350
-
351
- | 闸 | 何时 | 你要做的 |
352
- |---|---|---|
353
- | goals 审核 | Stage 0 后 | 过一遍 `goals/*.yaml`(验收合同) |
354
- | wave 边界 | 每批之后 | 看报告(pass / escalate / friction),批 merge 进 `integration` |
355
- | ⛔ real tier | M2 后 | 确认 billing.md L1–L5 已就位(`gs-dev`、L4 配额 2、$100 killswitch、清扫),说 go |
356
- | SHIP | 里程碑后 | 批准 push;prod migration 由主 loop 直接 apply + 对 live 验证 |
357
- | escalate | 任一 WU 2 轮不过 / goals 被改 / teardown 没清干净 | 看摘要,改 goals、拆 WU,或手动清资源 |
358
-
359
- ## runbook
360
-
361
- 1. 你 review 本文 + [accounts.md](accounts.md) + [billing.md](billing.md) + 各设计 md。
362
- 2. 我跑 **Stage 0** `gs-spec-goals` → 产出 `docs/platform/goals/*.yaml` → 你审 → commit;我记下每个 goal 的 `sha256`(给 verifier 做完整性核对,E2)。
363
- 3. **首个 build wave 前**:对每个目标 repo `git -C <repo> branch integration main`(E1);之后按依赖图逐批跑 `gs-build-wave`(args = 该批 WU + `goal_sha256` + `repo_roots` 绝对路径)→ 每批结束汇报 → 你批 merge 进各 repo 的 `integration`。
364
- 4. M1 / M2 由全新 Opus 用户 agent 在 sequence-testing 里走 mock E2E。
365
- 5. ⛔ 你确认 billing.md L1–L6 已就位并批 real tier → 每个 real WU 一个独立 run(R3→R1→R2 串行)+ M3–M5(每次 run 自带 teardown)。
366
- 6. SHIP。