Skip to content

Production Minimal Work Core Design v0.1

状态:Design candidate — Phase 1 implementation input
权威输入:spikes/minimal_work_core/contracts/v0_1/ 的九份冻结 contract。
范围:production Minimal Work Core 的 additive Phase 1;不采用 spike 实现代码。

1. 目标与冻结设计律

Phase 1 的唯一闭环是:创建 Work → 创建 Codex Execution → 通过既有 profile isolation dispatch → 发现 Codex thread ID → 保存 material projection/refs/events → 同一 Execution resume → 用户/host 显式关闭 Work。

设计遵守十条冻结律:Work 是有界工作的稳定 identity;Work 独立于 Execution;Execution 不决定 closure;native state provider-owned;连续 native identity 的 resume 不新建 Execution;provider replacement 新建 Execution 但不新建 Work;workflow 不属于 Core orchestration;ledger 只记 cross-system facts;Core 无 provider branch;外部资源只通过 Ref 引用。

2. Existing Repository Inventory

Existing capabilityReuse decisionBoundary
core.dbReuseSQLite connection、migration discovery、shared write lock;Phase 1 增量 migration,而非 spike JSON store
config.agent_box_home()Reusestorage root resolution;tests 继续通过 AGENT_BOX_HOME 隔离
resources.profile / agent registryConsumeCodex profile validation、metadata lookup;Core 不读取 profile config payload
launch.build_launch_plan()Consume via facade提供 bwrap argv/env/cwd;Core 绝不调用 launch.launch()
resources.sessionsPreserve, not depend onlegacy profile-launch process record,不能作为 Execution/native-session persistence
project_spacePreserve, optional Workspace authorityPhase 1 可接 WorkspaceRef,不重写 workspace lifecycle
current work/ package / migration 003 / work CLIPreserve, not reuse当前未提交实现有 roles、fixed workflow、phase、workspace、attempt/handoff;与冻结 contract 不兼容,必须双轨运行
ACP adapterPreserve, not use in Phase 1ACP session model 不等价于 Codex CLI JSONL thread identity

Compatibility conclusion

旧 Profile/launch/session/GUI 保留。新的 Core 应新增独立 work_core package 和 optional future CLI command;不改变 legacy work package。Phase 1 需要一个 CodexLaunchFacade:它消费 build_launch_plan(),自行以 Popen 启动 JSONL command,并将 process observation 与 legacy sessions record 分离。这样既复用 bwrap/profile isolation,也不让 Core 承担 launch.launch()SystemExit 与 legacy session side effect。

3. Domain Core

Work

text
Work(id, objective, lifecycle, closure_reason?, metadata, created_at, updated_at, version)

lifecycle ∈ {open, completed, abandoned}reopen 是明确 transition。metadata 是受限平面 str -> str,有长度/项数限制。

Work 不包含 profile、provider、session、workflow、phase、workspace bytes、artifact bytes、retry、scheduling、permissions 或 transcript。Execution outcome 不自动更新 Work lifecycle。

Execution

text
Execution(id, work_id, provider_id, projection, provenance, created_at,
          dispatched_at?, started_at?, ended_at?, version)

Native/input/output refs 均通过 relation table 关联。Execution 不包含 native JSONL、Codex config、thread history、checkpoint、process internals 或 arbitrary provider payload。

Projection

text
ExecutionProjection(
  phase: active | terminal | unknown,
  outcome: succeeded | failed | cancelled | abandoned | null,
  resumable_now: bool | null,
  freshness: observed | stale | unreachable,
  observed_at: timestamp
)

Validation:non-terminal phase 不得有 outcome;terminal phase 必须有 outcome;unknown 的 outcome 为 null;resumable_now 可为 null(native query unavailable)。waiting/queued/retrying/paused 不进入 Core vocabulary。

4. Runtime and Provider Contract

text
ExecutionProvider
  descriptor() -> ProviderDescriptor
  capabilities() -> ProviderCapabilities
  start(StartRequest) -> DispatchReceipt
  observe(NativeRef) -> ProviderObservation

optional, capability-qualified:
  resume(ResumeRequest), cancel(...), send_input(...), stream(...),
  pause(...), retry(...), approve(...), attach(...), reconnect(...)

ProviderCapabilities.supports_resume 描述 provider 的通用能力;Execution 的 projection.resumable_now 描述该 native instance 的当前事实。ExecutionService 在调用 resume 时必须同时检查二者。

Provider 只返回 provider-neutral ProviderObservation(projection、new refs、bounded diagnostic summary、optional native error code)。Core 不具有 if provider == "codex"

5. Ref and Event Ledger

Ref 是 immutable value:typeprovidernative_id、optional uri、bounded str -> str metadata。语义 type:SessionRef、WorkflowInstanceRef、RunRef、WorkspaceRef、ArtifactRef。禁止 nested payload、transcript、checkpoint blob、command output、graph 和 artifact bytes。

Event ledger 只写 material facts:WorkCreated、WorkCompleted、WorkReopened、ExecutionCreated、ExecutionDispatchRequested、NativeRefDiscovered、ExecutionStarted、ExecutionProjectionChanged、ExecutionTerminal、RefAttached。poll 没有 material change 时不写 event。

6. Persistence Proposal

在现有 agent-box.db 新增单一增量 migration(建议 004_minimal_work_core.sql),不改已有 001–003 表:

TablePurpose
core_worksWork current state、closure、bounded metadata、optimistic version
core_executionsExecution current projection、provider id、timestamps、optimistic version
core_execution_refsinput/output/native ref rows;type/provider/native_id/uri/metadata JSON(仅 flat map)
core_eventsappend-only material fact ledger;subject/idempotency key/type/data JSON(bounded fact data)
core_dispatchesdurable dispatch intent, idempotency key, state (requested/dispatched/reconciled) and provider correlation ref

projection 使用显式 scalar columns,不存 JSON blob。Ref metadata/event data 由 repository validation 后编码。SQLite transaction 覆盖“current state update + event append + version check”;native dispatch 永远在 transaction 之外。

Idempotency and restart recovery

  1. 先在 transaction 内创建 Execution + ExecutionDispatchRequested + dispatch intent(caller idempotency key 唯一)。
  2. 再调用 provider。thread ID 一旦从 JSONL 出现,transaction 原子地保存 SessionRef、projection、NativeRefDiscovered/Started。
  3. 若 process/Core 在两者之间崩溃,dispatch 保持 requested,Execution projection 为 unknown/stale;recovery 不重新盲发,而是按 provider-native correlation 能力 reconcile。Codex Phase 1 若没有已知 thread ID,标记 unknown 并要求显式 host recovery/abandon,而非猜测。

7. Error Model and Concurrency

Provider-neutral errors:ProviderUnavailableDispatchFailedNativeIdentityMissingObservationFailedCapabilityUnsupportedExecutionNotResumableInvalidProjectionConcurrencyConflict

每个 command 用 expected version compare-and-swap。并发 observe 只接受较新 observed_at 或返回 conflict;resume/cancel 以 Execution version 串行;close Work 不取消 active Execution,只记录显式 closure,host policy 决定后续行为。同一 Work 可以关联多个 Execution。

8. Codex Phase 1 Adapter

text
ExecutionService
  -> ProviderRegistry["codex-cli"]
  -> CodexExecutionProvider
  -> CodexLaunchFacade(build_launch_plan(profile, extra_args, cwd))
  -> bwrap + Codex CLI `exec --json` / `exec resume --json THREAD_ID`

Facade 从 LaunchPlan 获得隔离 argv/env/cwd,并替换末端 agent args;它不 import Work repositories。Codex provider 流式解析 JSONL:thread.started 发现 SessionRef;turn.started 投影 active;turn.completed 投影 terminal/succeeded 且根据 native session semantics 设置 resumable_now;turn.failed 投影 terminal/failed;malformed stream/exit without authoritative terminal event 为 unknown/stale 或 DispatchFailed。完整 JSONL 写入 provider-owned diagnostics location(如启用),Core 只保存 ArtifactRef/RunRef。

resume_execution(execution_id) 保持同一 execution_id,要求 SessionRef、provider supports resume 及 resumable_now is True。新 Codex thread 或 provider replacement 必须 create_execution

9. Directory Design

建议 additive package,避免触碰已有 agent_box.work

text
src/agent_box/work_core/
  models.py          # Work, Execution, Ref value types
  projection.py      # enums + validator
  events.py          # event types/value
  repository.py      # SQLite persistence/CAS
  services.py        # WorkService + ExecutionService
  errors.py
  registry.py
  providers/
    base.py
    codex.py
    codex_jsonl.py
    codex_launch.py

不在 Phase 1 修改 GUI;CLI integration 作为独立、非默认 command,且只在 services/tests 已稳定后添加。

10. Ownership Matrix

ConcernOwner
Work identity/objective/closureWork Core + explicit host command
Execution identity/current projectionExecution Core from provider observation
dispatch intent/idempotencyExecutionService + storage
native thread/process/transcriptCodex provider
profile/config/bwrap isolationexisting Agent-Box launch/profile capability
legacy launch session auditexisting sessions repository
workspace lifecycleexisting Workspace authority, not Phase 1 Core
artifact bytesprovider/artifact authority
event facts/refsCore persistence
scheduling/notification/orchestrationhost/extensions, out of scope

11. Phase 1 Slice, Tests and Migration

Only Codex is wired. Tests: Work lifecycle; projection validation; Ref bounds; registry fake provider; Codex JSONL parser; resume same execution; malformed/process failure; SQLite reload/events/native ref; architecture import boundary. No real Codex invocation in unit suite; an opt-in smoke uses a profile and isolated workspace.

Additive migration sequence: Phase 1 core tables/Codex facade; Phase 2 normalize other harnesses; Phase 3 LangGraph/Human/CI extensions; Phase 4 official TUI/CLI Work UX; Phase 5 GUI/ecosystem. Existing profile system, legacy sessions, GUI and uncommitted work/ package remain functional and untouched throughout.

12. Known Risks

Codex native dispatch correlation before thread.started is the major unresolved distributed-systems window. SQLite is single-host only but adequate for Phase 1 with explicit locks/CAS. A provider-owned diagnostic log needs retention/access control outside Core. The existing work/ package shares a concept name but has incompatible semantics; package isolation and dual-run documentation are mandatory until a separately authorized migration.

Contract Compliance

All ten frozen design laws are satisfied by this design. No hard architecture failure is required: no provider fields in Work; no transcript/checkpoint in Execution; Core imports provider interfaces only; no switch; completion does not close Work; same native identity resumes same Execution; Ref and EventLedger stay bounded; no scheduler/workflow engine.