Compare commits

...
23 changed files with 1204 additions and 0 deletions
@@ -0,0 +1,10 @@
# Independent Validator Result
- Model: `gpt-5.3-codex-spark`
- Reviewer identity: `gpt-5.3-codex-spark-validator`
- Broad live-review attempt: `TIMEOUT` after 600 seconds; no decision was accepted from that attempt.
- Narrow immutable evidence-bundle review: `SUCCESS`
- Cleanup review: `PASS`
- Release decision: `STOP_PREPRODUCTION`
- Verified: 10 Manifest records, 7 removed records, 3 retained roots, 7 local/remote Archive OID pairs, product OID equality, release/tag absence, and global dirty/locked/prunable all zero.
- Blocking finding: archived Portal Adapter `portal-surface` and `seed-ucc` commands returned non-zero.
@@ -0,0 +1,317 @@
{
"schema_version": "aios.incubator.worktree-archive.v1",
"status": "CLEANUP_REVIEWED_RELEASE_STOPPED",
"release_gate": "STOP_PREPRODUCTION",
"release_gate_reasons": [
"archived Portal Adapter portal-surface contract tests failed",
"archived Portal Adapter Django test could not execute because Django is absent on the validation host"
],
"inventory_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-archive-20260721T064301Z",
"archive_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-task-archive-20260721T070301Z",
"removal_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-task-removal-20260721T070843Z",
"controller_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-controller-migration-20260721T070749Z",
"longterm_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-longterm-clean-20260721T071346Z",
"global_gate_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-global-gate-20260721T071446Z",
"release_source": false,
"reviewed_count": 10,
"removed_count": 7,
"retained_active_count": 3,
"global_dirty_count": 0,
"locked_count": 0,
"prunable_count": 0,
"archive_validation": {
"passed_commands": 7,
"failed_commands": 1,
"blocked_commands": 1
},
"worktrees": [
{
"worktree_path": "/data/aios-gitops/worktrees/chatgpt/TASK-V2R1-PERSONAL-WEIXIN-GOLDEN-CONTRACT-R2-20260715",
"owner": "chatgpt",
"task_id": "TASK-V2R1-PERSONAL-WEIXIN-GOLDEN-CONTRACT-R2-20260715",
"source_branch": "design/v2r1-personal-weixin-golden-contract-r2-20260715",
"source_oid": "68d27879103990aac692207a8512b3725c6d0d41",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 36,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"channel-neutral versioned contract SDK and deterministic fixture validation pattern"
],
"excluded_items": [
"Personal-Weixin schemas, fixtures, security document and release-specific plan"
],
"archive_branch": "archive/chatgpt/TASK-V2R1-PERSONAL-WEIXIN-GOLDEN-CONTRACT-R2-20260715-20260721",
"archive_oid": "fe86e35257113853ba08b1438bc820bb4554e6e8",
"archive_remote_oid": "fe86e35257113853ba08b1438bc820bb4554e6e8",
"cleanup_method": "archive_commit_push_verify_then_worktree_remove_and_prune",
"removed_at": "2026-07-21T07:08:45Z",
"validation": "PASS: contract harness",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/chatgpt/TASK-V2R1-PERSONAL-WEIXIN-PORTAL-ADAPTER-20260715",
"owner": "chatgpt",
"task_id": "TASK-V2R1-PERSONAL-WEIXIN-PORTAL-ADAPTER-20260715",
"source_branch": "fix/v2r1-personal-weixin-portal-adapter-20260715",
"source_oid": "64270e74ba0835971ee20bf4d2b12b1d20b05533",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 2,
"secret_scan": {
"initial_violations": 1,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"generic auth-session state, expiry, challenge, replay and fail-closed policy"
],
"excluded_items": [
"UCC/OpenClaw/Weixin adapter implementation; incomplete portal surface; runtime-specific binding code"
],
"archive_branch": "archive/chatgpt/TASK-V2R1-PERSONAL-WEIXIN-PORTAL-ADAPTER-20260715-20260721",
"archive_oid": "79f529a91f8bf7cf3237feb01e98807ab5ad10b3",
"archive_remote_oid": "79f529a91f8bf7cf3237feb01e98807ab5ad10b3",
"cleanup_method": "archive_commit_push_verify_then_worktree_remove_and_prune",
"removed_at": "2026-07-21T07:08:46Z",
"validation": "REJECTED_FOR_ADOPTION: official-login tests pass; portal-surface tests fail; Django test blocked by missing dependency",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/chatgpt/TASK-WORKTREE-CONCURRENCY-CHATGPT-20260715T055106UTC8",
"owner": "chatgpt",
"task_id": "TASK-WORKTREE-CONCURRENCY-CHATGPT-20260715T055106UTC8",
"source_branch": "task/chatgpt/TASK-WORKTREE-CONCURRENCY-CHATGPT-20260715T055106UTC8",
"source_oid": "b05eb1babe9c657e8776c09eec71302166902cc3",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 2,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"registered-worktree classification and dirty-count governance model"
],
"excluded_items": [
"agent task/result documents and ACL probe evidence"
],
"archive_branch": "archive/chatgpt/TASK-WORKTREE-CONCURRENCY-CHATGPT-20260715T055106UTC8-20260721",
"archive_oid": "f0feed397dc67edab7daa16f0cdb5b553eca5668",
"archive_remote_oid": "f0feed397dc67edab7daa16f0cdb5b553eca5668",
"cleanup_method": "archive_commit_push_verify_then_worktree_remove_and_prune",
"removed_at": "2026-07-21T07:08:47Z",
"validation": "PASS: evidence integrity and zero-secret scan",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/codex/TASK-CODEX-AIOS-SPARK-RUNNER-PROVISIONING-20260717T103500UTC8",
"owner": "codex",
"task_id": "TASK-CODEX-AIOS-SPARK-RUNNER-PROVISIONING-20260717T103500UTC8",
"source_branch": "patch/chatgpt/v2r1-personal-weixin-b3-repair3-owner-20260717T102830UTC8",
"source_oid": "ef20c71247c6de6659e18fc57315da19d8a3834e",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 6,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"generic runner-provider preflight, immutable digest and reference-only credential contracts"
],
"excluded_items": [
"Spark-specific systemd, provisioning, rollback and production wiring"
],
"archive_branch": "archive/codex/TASK-CODEX-AIOS-SPARK-RUNNER-PROVISIONING-20260717T103500UTC8-20260721",
"archive_oid": "d97cd3642528bd3373fe4cf5161a5d99c0b9285f",
"archive_remote_oid": "d97cd3642528bd3373fe4cf5161a5d99c0b9285f",
"cleanup_method": "archive_commit_push_verify_then_worktree_remove_and_prune",
"removed_at": "2026-07-21T07:08:48Z",
"validation": "PASS: 27 pytest tests",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/openclaw/TASK-OPENCLAW-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-HARDEN-20260716T133000UTC8",
"owner": "openclaw",
"task_id": "TASK-OPENCLAW-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-HARDEN-20260716T133000UTC8",
"source_branch": "patch/openclaw/v2r1-personal-weixin-b3-evidence-hardening-20260716T133000UTC8",
"source_oid": "8d9c6da90fc8caa69b691d243c6fefb40b6b0575",
"remote_oid": "8d9c6da90fc8caa69b691d243c6fefb40b6b0575",
"dirty_files_before": 3,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"canonical evidence envelope, streaming hash and independent-review integrity policy"
],
"excluded_items": [
"Personal-Weixin B3 evidence tool, empty owner facts and release-specific output path"
],
"archive_branch": "archive/openclaw/TASK-OPENCLAW-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-HARDEN-20260716T133000UTC8-20260721",
"archive_oid": "2ddbc456124c02707dc23e8d6c241826d7026575",
"archive_remote_oid": "2ddbc456124c02707dc23e8d6c241826d7026575",
"cleanup_method": "archive_commit_push_verify_then_worktree_remove_and_prune",
"removed_at": "2026-07-21T07:08:49Z",
"validation": "PASS: compile, canonical template JSON and CLI help",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/openclaw/TASK-V2R1-OPENCLAW-WEIXIN-WEB-LOGIN-CONTRACT-20260715",
"owner": "openclaw",
"task_id": "TASK-V2R1-OPENCLAW-WEIXIN-WEB-LOGIN-CONTRACT-20260715",
"source_branch": "fix/v2r1-openclaw-weixin-web-login-contract-20260715",
"source_oid": "68d27879103990aac692207a8512b3725c6d0d41",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 20,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"generic auth-session state transitions and readiness/revocation contracts"
],
"excluded_items": [
"OpenClaw and Tencent Weixin patches, candidate evidence and channel-specific code"
],
"archive_branch": "archive/openclaw/TASK-V2R1-OPENCLAW-WEIXIN-WEB-LOGIN-CONTRACT-20260715-20260721",
"archive_oid": "d03b4ee34debe6e30ce2af233e2226b02e6dd029",
"archive_remote_oid": "d03b4ee34debe6e30ce2af233e2226b02e6dd029",
"cleanup_method": "archive_commit_push_verify_then_worktree_remove_and_prune",
"removed_at": "2026-07-21T07:08:50Z",
"validation": "PASS: Node contract tests",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/openclaw/TASK-WORKTREE-CONCURRENCY-OPENCLAW-20260715T055106UTC8",
"owner": "openclaw",
"task_id": "TASK-WORKTREE-CONCURRENCY-OPENCLAW-20260715T055106UTC8",
"source_branch": "task/openclaw/TASK-WORKTREE-CONCURRENCY-OPENCLAW-20260715T055106UTC8",
"source_oid": "b05eb1babe9c657e8776c09eec71302166902cc3",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 3,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"registered-worktree classification and cleanup authorization boundary"
],
"excluded_items": [
"agent task/result documents and ACL probe evidence"
],
"archive_branch": "archive/openclaw/TASK-WORKTREE-CONCURRENCY-OPENCLAW-20260715T055106UTC8-20260721",
"archive_oid": "d9a85bb86cc09c117d63de803a404ee5a864e7c1",
"archive_remote_oid": "d9a85bb86cc09c117d63de803a404ee5a864e7c1",
"cleanup_method": "archive_commit_push_verify_then_worktree_remove_and_prune",
"removed_at": "2026-07-21T07:08:51Z",
"validation": "PASS: evidence integrity and zero-secret scan",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/codex",
"owner": "codex",
"task_id": "codex-long-term-root",
"source_branch": "acceptance/codex/TASK-CODEX-GITOPS-SECRET-ACL-AND-IDENTITY-HARDENING-20260715T004818UTC8-FINAL",
"source_oid": "b87266d63f4d16ba25b9c0041d6769822dfa99d4",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 56,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"registered child-worktree governance classification"
],
"excluded_items": [
"all 55 retained registered child worktrees and their contents"
],
"archive_branch": "acceptance/codex/TASK-CODEX-GITOPS-SECRET-ACL-AND-IDENTITY-HARDENING-20260715T004818UTC8-FINAL",
"archive_oid": "0193a12b57c4974888b25753fd2bfb1f2028909b",
"archive_remote_oid": "0193a12b57c4974888b25753fd2bfb1f2028909b",
"cleanup_method": "retain active long-term root; commit exact registered-child ignore list",
"removed_at": null,
"validation": "PASS: 55 untracked entries exactly matched 55 registered child worktrees; final clean",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/controller",
"owner": "controller",
"task_id": "controller-long-term-root",
"source_branch": "DETACHED",
"source_oid": "102d2306f05397374fc91c711767021c5d9f41f9",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 11,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"runtime-state separation policy"
],
"excluded_items": [
"generated health/watcher state and duplicate controller-run audit records"
],
"archive_branch": "archive/controller/runtime-baseline-20260721",
"archive_oid": "102d2306f05397374fc91c711767021c5d9f41f9",
"archive_remote_oid": "102d2306f05397374fc91c711767021c5d9f41f9",
"cleanup_method": "retain active source root; migrate watcher state to runtime directory; restore tracked generated state; remove only hash-matched duplicates",
"removed_at": null,
"validation": "PASS: watcher, model API and autonomous controller active; final clean",
"reviewer": "gpt-5.3-codex-spark-validator"
},
{
"worktree_path": "/data/aios-gitops/worktrees/openclaw",
"owner": "openclaw",
"task_id": "openclaw-long-term-root",
"source_branch": "acceptance/openclaw/TASK-CODEX-GITOPS-SECRET-ACL-AND-IDENTITY-HARDENING-20260715T004818UTC8-FINAL",
"source_oid": "6cd0f5aa0ad28f767ffd5396c29d1a9182f88c43",
"remote_oid": "ABSENT_AT_INVENTORY",
"dirty_files_before": 5,
"secret_scan": {
"initial_violations": 0,
"final_violations": 0,
"secrets_recorded": false
},
"adopted_items": [
"registered child-worktree governance classification"
],
"excluded_items": [
"both retained registered child worktrees and their contents"
],
"archive_branch": "acceptance/openclaw/TASK-CODEX-GITOPS-SECRET-ACL-AND-IDENTITY-HARDENING-20260715T004818UTC8-FINAL",
"archive_oid": "633c8308f53b0ad04ce054ceafb624cb0904cbf4",
"archive_remote_oid": "633c8308f53b0ad04ce054ceafb624cb0904cbf4",
"cleanup_method": "retain active long-term root; commit exact registered-child ignore list",
"removed_at": null,
"validation": "PASS: 2 untracked entries exactly matched 2 registered child worktrees; final clean",
"reviewer": "gpt-5.3-codex-spark-validator"
}
],
"unknown_value_policy": "UNVERIFIED_OWNER_INPUT_REQUIRED",
"secrets_recorded": false,
"reviewer": "gpt-5.3-codex-spark-validator",
"reviewer_decision": {
"cleanup_review": "PASS",
"release_decision": "STOP_PREPRODUCTION",
"verified_counts": {
"manifest_records": 10,
"removed_records": 7,
"retained_roots": 3,
"archive_oid_local_remote_pairs": 7,
"global_dirty": 0,
"global_locked": 0,
"global_prunable": 0
},
"finding": "portal-surface and seed-ucc archive validation commands returned non-zero",
"review_scope": "compact immutable evidence bundle after one broader live-review timeout"
}
}
@@ -0,0 +1,19 @@
# Worktree Cleanup Result
Status: `CLEANUP_REVIEWED_RELEASE_STOPPED`
- Reviewed: `10/10`
- Archived and removed: `7`
- Retained active and cleaned: `3`
- Global dirty worktrees: `0`
- Locked: `0`
- Prunable: `0`
- Product OID: `fb739f6e8ff9c031d319221ace68dce157694086`
- Incubator OID before this manifest commit: `4487a774fdeec51bc49253c2ad494c19d1b1c3e2`
- Release branch created: `false`
- V2R1C1 tag created: `false`
- Release decision: `STOP_PREPRODUCTION`
The stop decision is evidence-driven: the archived Portal Adapter portal-surface contract suite failed, and its Django test could not run because Django is absent on the host. No failed archive candidate was adopted into the incubator or product branch.
Independent reviewer: `gpt-5.3-codex-spark-validator`; cleanup `PASS`; release `STOP_PREPRODUCTION`.
@@ -0,0 +1,3 @@
"""Future AIOS capabilities isolated from the V2R1C1 release line."""
__all__: list[str] = []
@@ -0,0 +1,64 @@
"""Channel-neutral adapter contracts for future evaluation."""
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Mapping, Protocol, Sequence, runtime_checkable
class AdapterHealthStatus(str, Enum):
HEALTHY = "healthy"
DEGRADED = "degraded"
UNAVAILABLE = "unavailable"
@dataclass(frozen=True)
class AdapterHealth:
status: AdapterHealthStatus
observed_at: str
details: Mapping[str, Any] = field(default_factory=dict)
@dataclass(frozen=True)
class AdapterCapability:
name: str
version: str = "1"
metadata: Mapping[str, Any] = field(default_factory=dict)
@dataclass(frozen=True)
class AdapterSession:
session_id: str
tenant_id: str
state: str
expires_at: str | None = None
metadata: Mapping[str, Any] = field(default_factory=dict)
@dataclass(frozen=True)
class AdapterResult:
ok: bool
state: str
output: Mapping[str, Any] = field(default_factory=dict)
error: Mapping[str, Any] = field(default_factory=dict)
@runtime_checkable
class ChannelAdapter(Protocol):
def health(self) -> AdapterHealth: ...
def capabilities(self) -> Sequence[AdapterCapability]: ...
def open_session(self, *, tenant_id: str) -> AdapterSession: ...
def execute(
self, *, session: AdapterSession, action: str, payload: Mapping[str, Any]
) -> AdapterResult: ...
def cancel(self, *, session: AdapterSession) -> AdapterResult: ...
@runtime_checkable
class PortalAdapter(ChannelAdapter, Protocol):
"""Marker protocol for user-facing portal adapters."""
@@ -0,0 +1,66 @@
"""Platform-neutral authentication-session state machine."""
from __future__ import annotations
from dataclasses import dataclass, replace
from enum import Enum
from typing import Mapping, Any
class AuthSessionState(str, Enum):
CREATED = "CREATED"
WAITING_FOR_USER = "WAITING_FOR_USER"
USER_CONFIRMED = "USER_CONFIRMED"
AUTHENTICATED = "AUTHENTICATED"
EXPIRED = "EXPIRED"
CANCELLED = "CANCELLED"
FAILED = "FAILED"
_TRANSITIONS = {
AuthSessionState.CREATED: {
AuthSessionState.WAITING_FOR_USER,
AuthSessionState.CANCELLED,
AuthSessionState.FAILED,
},
AuthSessionState.WAITING_FOR_USER: {
AuthSessionState.USER_CONFIRMED,
AuthSessionState.EXPIRED,
AuthSessionState.CANCELLED,
AuthSessionState.FAILED,
},
AuthSessionState.USER_CONFIRMED: {
AuthSessionState.AUTHENTICATED,
AuthSessionState.EXPIRED,
AuthSessionState.CANCELLED,
AuthSessionState.FAILED,
},
}
class InvalidAuthSessionTransition(ValueError):
pass
@dataclass(frozen=True)
class AuthSession:
session_id: str
tenant_id: str
state: AuthSessionState = AuthSessionState.CREATED
expires_at: str | None = None
metadata: Mapping[str, Any] | None = None
def transition(self, target: AuthSessionState) -> "AuthSession":
allowed = _TRANSITIONS.get(self.state, set())
if target not in allowed:
raise InvalidAuthSessionTransition(f"{self.state.value} -> {target.value}")
return replace(self, state=target)
@property
def terminal(self) -> bool:
return self.state in {
AuthSessionState.AUTHENTICATED,
AuthSessionState.EXPIRED,
AuthSessionState.CANCELLED,
AuthSessionState.FAILED,
}
@@ -0,0 +1,147 @@
"""Incubator-only versioned contract primitives.
This module distills the reusable contract-first practices observed in the
Personal Weixin golden-contract work without importing channel-specific fields
into the AIOS control plane. It is intentionally not imported by production
AIOS V2R1 modules.
"""
from __future__ import annotations
import hashlib
import json
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Mapping, Sequence
class ContractViolation(ValueError):
"""A payload does not satisfy its declared contract."""
class Compatibility(str, Enum):
EXACT = "exact"
BACKWARD_COMPATIBLE = "backward_compatible"
INCOMPATIBLE = "incompatible"
def canonical_json_bytes(value: Mapping[str, Any]) -> bytes:
return json.dumps(
dict(value),
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
default=str,
).encode("utf-8")
def payload_digest(value: Mapping[str, Any]) -> str:
return hashlib.sha256(canonical_json_bytes(value)).hexdigest()
@dataclass(frozen=True, order=True)
class ContractVersion:
major: int
minor: int
patch: int = 0
def __post_init__(self) -> None:
if min(self.major, self.minor, self.patch) < 0:
raise ValueError("contract version components must be non-negative")
@classmethod
def parse(cls, value: str) -> "ContractVersion":
parts = str(value or "").strip().split(".")
if len(parts) not in {2, 3} or any(not item.isdigit() for item in parts):
raise ValueError("contract version must use MAJOR.MINOR[.PATCH]")
numbers = [int(item) for item in parts]
if len(numbers) == 2:
numbers.append(0)
return cls(*numbers)
def __str__(self) -> str:
return f"{self.major}.{self.minor}.{self.patch}"
@dataclass(frozen=True)
class VersionedContract:
name: str
version: ContractVersion
required_fields: Sequence[str]
optional_fields: Sequence[str] = ()
forbidden_fields: Sequence[str] = ()
secret_fields: Sequence[str] = ()
allow_unknown_fields: bool = False
metadata: Mapping[str, Any] = field(default_factory=dict)
def __post_init__(self) -> None:
name = str(self.name or "").strip()
if not name:
raise ValueError("contract name is required")
object.__setattr__(self, "name", name)
required = frozenset(str(item).strip() for item in self.required_fields if str(item).strip())
optional = frozenset(str(item).strip() for item in self.optional_fields if str(item).strip())
forbidden = frozenset(str(item).strip() for item in self.forbidden_fields if str(item).strip())
secrets = frozenset(str(item).strip() for item in self.secret_fields if str(item).strip())
if required & forbidden:
raise ValueError("required fields cannot also be forbidden")
if required & optional:
raise ValueError("required and optional fields must be disjoint")
object.__setattr__(self, "required_fields", tuple(sorted(required)))
object.__setattr__(self, "optional_fields", tuple(sorted(optional)))
object.__setattr__(self, "forbidden_fields", tuple(sorted(forbidden)))
object.__setattr__(self, "secret_fields", tuple(sorted(secrets)))
object.__setattr__(self, "metadata", json.loads(json.dumps(dict(self.metadata), default=str)))
@property
def allowed_fields(self) -> frozenset[str]:
return frozenset((*self.required_fields, *self.optional_fields))
def validate(self, payload: Mapping[str, Any]) -> dict[str, Any]:
normalized = json.loads(json.dumps(dict(payload), ensure_ascii=False, default=str))
fields = set(normalized)
missing = sorted(set(self.required_fields) - fields)
forbidden = sorted(set(self.forbidden_fields) & fields)
unknown = sorted(fields - self.allowed_fields)
if missing:
raise ContractViolation(f"missing required fields: {missing}")
if forbidden:
raise ContractViolation(f"forbidden fields present: {forbidden}")
if unknown and not self.allow_unknown_fields:
raise ContractViolation(f"unknown fields present: {unknown}")
return normalized
def redact(self, payload: Mapping[str, Any]) -> dict[str, Any]:
normalized = json.loads(json.dumps(dict(payload), ensure_ascii=False, default=str))
for field_name in self.secret_fields:
if field_name in normalized:
normalized[field_name] = "***"
return normalized
def compatibility_with(self, previous: "VersionedContract") -> Compatibility:
if self.name != previous.name:
return Compatibility.INCOMPATIBLE
if self.version == previous.version and self == previous:
return Compatibility.EXACT
if self.version.major != previous.version.major:
return Compatibility.INCOMPATIBLE
if not set(previous.required_fields).issubset(self.allowed_fields):
return Compatibility.INCOMPATIBLE
if set(previous.allowed_fields) & set(self.forbidden_fields):
return Compatibility.INCOMPATIBLE
if not self.allow_unknown_fields and not set(previous.allowed_fields).issubset(self.allowed_fields):
return Compatibility.INCOMPATIBLE
return Compatibility.BACKWARD_COMPATIBLE
def descriptor(self) -> dict[str, Any]:
value = {
"name": self.name,
"version": str(self.version),
"required_fields": list(self.required_fields),
"optional_fields": list(self.optional_fields),
"forbidden_fields": list(self.forbidden_fields),
"secret_fields": list(self.secret_fields),
"allow_unknown_fields": self.allow_unknown_fields,
"metadata": dict(self.metadata),
}
value["descriptor_digest"] = payload_digest(value)
return value
@@ -0,0 +1,90 @@
"""Evidence integrity and replacement-audit primitives."""
from __future__ import annotations
import hashlib
import json
from dataclasses import dataclass, field, replace
from pathlib import Path
from typing import Any, Mapping, Sequence
class EvidenceIntegrityError(RuntimeError):
pass
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(65536), b""):
digest.update(chunk)
return digest.hexdigest()
@dataclass(frozen=True)
class LogReplacement:
artifact: str
previous_sha256: str
replacement_sha256: str
reason: str
replaced_at: str
@dataclass(frozen=True)
class EvidenceManifest:
command: Sequence[str]
start_time: str
end_time: str
exit_code: int
artifacts: Mapping[str, str]
result_summary: Mapping[str, Any] = field(default_factory=dict)
reviewer_status: str = "PENDING"
supersedes: Sequence[str] = ()
replacement_audit: Sequence[LogReplacement] = ()
def validate(self, root: Path) -> None:
for relative, expected in self.artifacts.items():
path = (root / relative).resolve()
if root.resolve() not in path.parents:
raise EvidenceIntegrityError("artifact escapes evidence root")
if not path.is_file():
raise EvidenceIntegrityError(f"artifact missing: {relative}")
actual = sha256_file(path)
if actual != expected:
raise EvidenceIntegrityError(f"artifact hash mismatch: {relative}")
def replace_artifact(
self, *, artifact: str, replacement_sha256: str, reason: str, replaced_at: str
) -> "EvidenceManifest":
previous = self.artifacts.get(artifact)
if previous is None:
raise EvidenceIntegrityError("replacement target is not registered")
if not reason.strip():
raise EvidenceIntegrityError("replacement reason is required")
updated = dict(self.artifacts)
updated[artifact] = replacement_sha256
audit = LogReplacement(
artifact=artifact,
previous_sha256=previous,
replacement_sha256=replacement_sha256,
reason=reason,
replaced_at=replaced_at,
)
return replace(
self,
artifacts=updated,
replacement_audit=(*self.replacement_audit, audit),
)
def as_dict(self) -> dict[str, Any]:
return {
"command": list(self.command),
"start_time": self.start_time,
"end_time": self.end_time,
"exit_code": self.exit_code,
"artifacts": dict(self.artifacts),
"result_summary": json.loads(json.dumps(dict(self.result_summary), default=str)),
"reviewer_status": self.reviewer_status,
"supersedes": list(self.supersedes),
"replacement_audit": [item.__dict__ for item in self.replacement_audit],
}
@@ -0,0 +1,64 @@
"""Provider-neutral runner lifecycle contracts."""
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Mapping, Protocol, runtime_checkable
class RunnerStatus(str, Enum):
PROVISIONING = "provisioning"
READY = "ready"
RUNNING = "running"
CANCELLED = "cancelled"
FAILED = "failed"
DEPROVISIONED = "deprovisioned"
@dataclass(frozen=True)
class RunnerHandle:
runner_id: str
provider: str
status: RunnerStatus
metadata: Mapping[str, Any] = field(default_factory=dict)
@dataclass(frozen=True)
class RunnerHealth:
ok: bool
status: RunnerStatus
observed_at: str
details: Mapping[str, Any] = field(default_factory=dict)
@dataclass(frozen=True)
class RunnerExecution:
execution_id: str
runner_id: str
status: RunnerStatus
exit_code: int | None = None
@dataclass(frozen=True)
class RunnerEvidence:
execution_id: str
artifacts: Mapping[str, str]
summary: Mapping[str, Any] = field(default_factory=dict)
@runtime_checkable
class RunnerProvider(Protocol):
def provision(self, request: Mapping[str, Any]) -> RunnerHandle: ...
def health(self, handle: RunnerHandle) -> RunnerHealth: ...
def execute(
self, handle: RunnerHandle, request: Mapping[str, Any]
) -> RunnerExecution: ...
def cancel(self, execution: RunnerExecution) -> RunnerExecution: ...
def collect_evidence(self, execution: RunnerExecution) -> RunnerEvidence: ...
def deprovision(self, handle: RunnerHandle) -> RunnerHandle: ...
@@ -0,0 +1,102 @@
"""Explicit worktree ownership and release-blocking classification."""
from __future__ import annotations
from dataclasses import dataclass, replace
from enum import Enum
from pathlib import PurePosixPath
from typing import Iterable
class WorktreeState(str, Enum):
ACTIVE = "ACTIVE"
READY_TO_COMMIT = "READY_TO_COMMIT"
COMMITTED = "COMMITTED"
ARCHIVED = "ARCHIVED"
OWNER_REVIEW_REQUIRED = "OWNER_REVIEW_REQUIRED"
TRUSTED_RUNTIME_DIRTY = "TRUSTED_RUNTIME_DIRTY"
STALE_CLEANUP_REQUIRED = "STALE_CLEANUP_REQUIRED"
REMOVED = "REMOVED"
@dataclass(frozen=True)
class WorktreeRecord:
path: str
owner: str
task_id: str
branch: str
base_oid: str
current_oid: str
heartbeat_at: str | None = None
dirty_count: int = 0
locked: bool = False
prunable: bool = False
active_runtime: bool = False
archive_oid: str | None = None
removed_at: str | None = None
def __post_init__(self) -> None:
if not PurePosixPath(self.path).is_absolute():
raise ValueError("worktree path must be absolute")
if not self.owner or not self.task_id or not self.current_oid:
raise ValueError("owner, task_id and current_oid are required")
if self.dirty_count < 0:
raise ValueError("dirty_count cannot be negative")
@property
def state(self) -> WorktreeState:
if self.removed_at:
return WorktreeState.REMOVED
if self.locked or self.prunable:
return WorktreeState.STALE_CLEANUP_REQUIRED
if self.dirty_count and self.active_runtime:
return WorktreeState.TRUSTED_RUNTIME_DIRTY
if self.dirty_count:
return WorktreeState.OWNER_REVIEW_REQUIRED
if self.archive_oid:
return WorktreeState.ARCHIVED
if self.current_oid != self.base_oid:
return WorktreeState.READY_TO_COMMIT
return WorktreeState.ACTIVE
@property
def release_blocking(self) -> bool:
return self.state in {
WorktreeState.OWNER_REVIEW_REQUIRED,
WorktreeState.TRUSTED_RUNTIME_DIRTY,
WorktreeState.STALE_CLEANUP_REQUIRED,
}
class WorktreeRegistry:
def __init__(self, records: Iterable[WorktreeRecord] = ()) -> None:
self._records: dict[str, WorktreeRecord] = {}
for record in records:
self.upsert(record)
def upsert(self, record: WorktreeRecord) -> None:
self._records[record.path] = record
def get(self, path: str) -> WorktreeRecord:
return self._records[path]
def mark_archived(self, path: str, archive_oid: str) -> WorktreeRecord:
if not archive_oid:
raise ValueError("archive_oid is required")
current = self.get(path)
if current.dirty_count:
raise ValueError("dirty worktree cannot be marked archived")
updated = replace(current, archive_oid=archive_oid)
self.upsert(updated)
return updated
def release_blockers(self) -> tuple[WorktreeRecord, ...]:
return tuple(
sorted(
(record for record in self._records.values() if record.release_blocking),
key=lambda item: item.path,
)
)
def snapshot(self) -> tuple[WorktreeRecord, ...]:
return tuple(sorted(self._records.values(), key=lambda item: item.path))
+9
View File
@@ -0,0 +1,9 @@
# Adoption Plan
1. Keep all candidates on the future incubator branch.
2. Require a named product requirement and threat model for each candidate.
3. Validate API stability, tenant isolation, secret handling and rollback independently.
4. Adopt one module at a time through a future release branch.
5. Never merge this branch into `V2R1C1`.
Current status for every module is `INCUBATING`; none is approved for production.
+14
View File
@@ -0,0 +1,14 @@
# Incubator Architecture
The incubator is a sibling capability area under `active-runtime/app/aios_incubator`. It has no import edge from `aios_v2`, `aios_openclaw` or `aios_hermes`.
| Module | Boundary |
|---|---|
| `contracts` | Versioning, required/optional/forbidden fields, compatibility and redaction |
| `adapters` | Channel-neutral health, capability, session and result protocols |
| `worktree_governance` | Registry facts, state classification and release blockers |
| `runners` | Provider-neutral provision/health/execute/cancel/evidence/deprovision contract |
| `evidence` | Artifact hashes, reviewer state, supersession and log replacement audit |
| `auth_session` | Generic user-mediated authentication lifecycle |
No module owns a production queue, lease, task state machine, credential store or deployment controller.
+10
View File
@@ -0,0 +1,10 @@
# Feature Matrix
| Capability | Source category | Adopted | Explicit exclusions | Status |
|---|---|---|---|---|
| Contract SDK | Golden Contract | schema semantics, compatibility, redaction, tests | Weixin fields and flows | INCUBATING |
| Adapter protocols | Portal Adapter | generic health/capability/session/result | Weixin implementation | INCUBATING |
| Worktree governance | Concurrency tasks | owner/task/OID/heartbeat/dirty/lock/prune/release blocking | task-specific ACL probes | INCUBATING |
| Runner provider | Spark provisioning | generic lifecycle methods | Spark credentials and fixed host paths | INCUBATING |
| Evidence framework | B3 hardening | manifest/hash/reviewer/supersession/replacement audit | Personal-Weixin evidence facts | INCUBATING |
| Auth session | Web login contract | generic states and transitions | QR, cookies and account identifiers | INCUBATING |
+14
View File
@@ -0,0 +1,14 @@
# AIOS Future Incubator
This tree contains channel-neutral capabilities distilled from archived AIOS task worktrees. It is intentionally excluded from `V2R1C1` and must not be imported by production AIOS modules without a separate adoption review.
Current candidates:
- versioned contract SDK;
- channel/portal adapter protocols;
- worktree ownership and release-blocking registry;
- provider-neutral runner lifecycle;
- evidence integrity and replacement audit;
- authentication-session state machine.
Platform implementations, credentials, cookies, QR payloads, account fields, runtime logs and fixed deployment paths are excluded.
@@ -0,0 +1,28 @@
# Worktree Archive Manifest
Status: `CLEANUP_REVIEWED_RELEASE_STOPPED`
Release gate: `STOP_PREPRODUCTION`
The machine-readable authority is `.agent/results/incubator/WORKTREE-ARCHIVE-MANIFEST.json`. Ten of ten named worktrees were reviewed: seven task worktrees were archived, pushed, verified and removed; three active long-term roots were retained and made clean.
The incubator is not a release source and was not merged into V2R1C1. The archived Portal Adapter is explicitly rejected for adoption because its portal-surface contract tests fail; its Django test is also blocked by a missing host dependency.
| # | Worktree | Decision | Archive / retained OID | Validation |
|---:|---|---|---|---|
| 1 | `TASK-V2R1-PERSONAL-WEIXIN-GOLDEN-CONTRACT-R2-20260715` | removed | `fe86e35257113853ba08b1438bc820bb4554e6e8` | PASS: contract harness |
| 2 | `TASK-V2R1-PERSONAL-WEIXIN-PORTAL-ADAPTER-20260715` | removed | `79f529a91f8bf7cf3237feb01e98807ab5ad10b3` | REJECTED_FOR_ADOPTION: official-login tests pass; portal-surface tests fail; Django test blocked by missing dependency |
| 3 | `TASK-WORKTREE-CONCURRENCY-CHATGPT-20260715T055106UTC8` | removed | `f0feed397dc67edab7daa16f0cdb5b553eca5668` | PASS: evidence integrity and zero-secret scan |
| 4 | `TASK-CODEX-AIOS-SPARK-RUNNER-PROVISIONING-20260717T103500UTC8` | removed | `d97cd3642528bd3373fe4cf5161a5d99c0b9285f` | PASS: 27 pytest tests |
| 5 | `TASK-OPENCLAW-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-HARDEN-20260716T133000UTC8` | removed | `2ddbc456124c02707dc23e8d6c241826d7026575` | PASS: compile, canonical template JSON and CLI help |
| 6 | `TASK-V2R1-OPENCLAW-WEIXIN-WEB-LOGIN-CONTRACT-20260715` | removed | `d03b4ee34debe6e30ce2af233e2226b02e6dd029` | PASS: Node contract tests |
| 7 | `TASK-WORKTREE-CONCURRENCY-OPENCLAW-20260715T055106UTC8` | removed | `d9a85bb86cc09c117d63de803a404ee5a864e7c1` | PASS: evidence integrity and zero-secret scan |
| 8 | `codex-long-term-root` | retained-active | `0193a12b57c4974888b25753fd2bfb1f2028909b` | PASS: 55 untracked entries exactly matched 55 registered child worktrees; final clean |
| 9 | `controller-long-term-root` | retained-active | `102d2306f05397374fc91c711767021c5d9f41f9` | PASS: watcher, model API and autonomous controller active; final clean |
| 10 | `openclaw-long-term-root` | retained-active | `633c8308f53b0ad04ce054ceafb624cb0904cbf4` | PASS: 2 untracked entries exactly matched 2 registered child worktrees; final clean |
## Independent review
Reviewer: `gpt-5.3-codex-spark-validator`
Cleanup review: `PASS`; release decision: `STOP_PREPRODUCTION`. The reviewer matched ten Manifest records, seven archive/removal OID pairs and three retained roots, then preserved the stop decision because `portal-surface` and `seed-ucc` returned non-zero.
@@ -0,0 +1,12 @@
# Worktree Cleanup Authorization
Owner authorization source: `AIOS V2R1C1 最终归档、清理、验证与上线执行命令`, received `2026-07-21`.
The authorization is limited to the ten named dirty worktrees. Before removal, each task worktree requires status/diff evidence, zero secret violations, a pushed archive OID, local/remote OID equality and a clean workspace. Active long-term worktrees must be retained when a service depends on them and must be cleaned without deleting the service path.
Forbidden cleanup methods:
- `git reset --hard`;
- `git clean -fdx`;
- deleting active Controller or OpenClaw roots;
- deleting content before its archive OID and artifact hashes are verified.
@@ -0,0 +1,9 @@
{
"type": "branch",
"branch": "patch/chatgpt/AIOS-V2R1-FUTURE-INCUBATOR-20260721",
"base": "fb739f6e8ff9c031d319221ace68dce157694086",
"created_by": "chatgpt-gitops-bot",
"created_at": "2026-07-21T06:30:22Z",
"direct_main_push": false,
"owner_approval_required": true
}
+1
View File
@@ -0,0 +1 @@
"""Incubator-only test suite."""
@@ -0,0 +1,30 @@
from __future__ import annotations
import sys
import unittest
from pathlib import Path
APP = Path(__file__).resolve().parents[2] / "active-runtime" / "app"
sys.path.insert(0, str(APP))
from aios_incubator.adapters import AdapterCapability, AdapterResult, AdapterSession
from aios_incubator.runners import RunnerExecution, RunnerStatus
class AdapterAndRunnerContractTests(unittest.TestCase):
def test_adapter_values_are_channel_neutral(self) -> None:
session = AdapterSession("session-1", "tenant-1", "waiting")
capability = AdapterCapability("messages.read")
result = AdapterResult(True, "completed", {"count": 1})
self.assertEqual(session.tenant_id, "tenant-1")
self.assertEqual(capability.version, "1")
self.assertTrue(result.ok)
def test_runner_execution_has_provider_neutral_status(self) -> None:
execution = RunnerExecution("exec-1", "runner-1", RunnerStatus.RUNNING)
self.assertEqual(execution.status, RunnerStatus.RUNNING)
self.assertIsNone(execution.exit_code)
if __name__ == "__main__":
unittest.main()
+34
View File
@@ -0,0 +1,34 @@
from __future__ import annotations
import sys
import unittest
from pathlib import Path
APP = Path(__file__).resolve().parents[2] / "active-runtime" / "app"
sys.path.insert(0, str(APP))
from aios_incubator.auth_session import (
AuthSession,
AuthSessionState,
InvalidAuthSessionTransition,
)
class AuthSessionTests(unittest.TestCase):
def test_successful_authentication_flow(self) -> None:
session = AuthSession("session-1", "tenant-1")
session = session.transition(AuthSessionState.WAITING_FOR_USER)
session = session.transition(AuthSessionState.USER_CONFIRMED)
session = session.transition(AuthSessionState.AUTHENTICATED)
self.assertTrue(session.terminal)
def test_expiry_cancel_failure_and_invalid_transition(self) -> None:
waiting = AuthSession("s", "t").transition(AuthSessionState.WAITING_FOR_USER)
for target in (AuthSessionState.EXPIRED, AuthSessionState.CANCELLED, AuthSessionState.FAILED):
self.assertTrue(waiting.transition(target).terminal)
with self.assertRaises(InvalidAuthSessionTransition):
waiting.transition(AuthSessionState.AUTHENTICATED)
if __name__ == "__main__":
unittest.main()
+54
View File
@@ -0,0 +1,54 @@
from __future__ import annotations
import sys
import unittest
from pathlib import Path
APP = Path(__file__).resolve().parents[2] / "active-runtime" / "app"
sys.path.insert(0, str(APP))
from aios_incubator.contracts import (
Compatibility,
ContractVersion,
ContractViolation,
VersionedContract,
)
class ContractTests(unittest.TestCase):
def test_validation_redaction_and_descriptor(self) -> None:
contract = VersionedContract(
name="channel.request",
version=ContractVersion.parse("1.2"),
required_fields=("request_id",),
optional_fields=("credential_ref",),
forbidden_fields=("credential_plain",),
secret_fields=("credential_ref",),
)
value = contract.validate(
{"request_id": "request-1", "credential_ref": "secretref:channel/test"}
)
self.assertEqual(contract.redact(value)["credential_ref"], "***")
self.assertEqual(len(contract.descriptor()["descriptor_digest"]), 64)
def test_missing_forbidden_and_unknown_fields_fail(self) -> None:
contract = VersionedContract(
name="channel.request",
version=ContractVersion(1, 0),
required_fields=("request_id",),
forbidden_fields=("credential_plain",),
)
for payload in ({}, {"request_id": "x", "credential_plain": "x"}, {"request_id": "x", "extra": 1}):
with self.subTest(payload=payload), self.assertRaises(ContractViolation):
contract.validate(payload)
def test_compatibility_is_explicit(self) -> None:
previous = VersionedContract("event", ContractVersion(1, 0), ("id",), ("kind",))
compatible = VersionedContract("event", ContractVersion(1, 1), ("id",), ("kind", "trace"))
breaking = VersionedContract("event", ContractVersion(2, 0), ("id",))
self.assertEqual(compatible.compatibility_with(previous), Compatibility.BACKWARD_COMPATIBLE)
self.assertEqual(breaking.compatibility_with(previous), Compatibility.INCOMPATIBLE)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,49 @@
from __future__ import annotations
import sys
import tempfile
import unittest
from pathlib import Path
APP = Path(__file__).resolve().parents[2] / "active-runtime" / "app"
sys.path.insert(0, str(APP))
from aios_incubator.evidence import EvidenceIntegrityError, EvidenceManifest, sha256_file
class EvidenceManifestTests(unittest.TestCase):
def test_hash_validation_and_replacement_audit(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
log = root / "step.log"
log.write_text("first\n", encoding="utf-8")
manifest = EvidenceManifest(
command=("validate",),
start_time="2026-07-21T00:00:00Z",
end_time="2026-07-21T00:00:01Z",
exit_code=0,
artifacts={"step.log": sha256_file(log)},
)
manifest.validate(root)
log.write_text("replacement\n", encoding="utf-8")
with self.assertRaises(EvidenceIntegrityError):
manifest.validate(root)
replacement = manifest.replace_artifact(
artifact="step.log",
replacement_sha256=sha256_file(log),
reason="superseded invalid harness output",
replaced_at="2026-07-21T00:01:00Z",
)
replacement.validate(root)
self.assertEqual(len(replacement.replacement_audit), 1)
def test_missing_replacement_reason_is_rejected(self) -> None:
manifest = EvidenceManifest(("x",), "s", "e", 0, {"a": "0" * 64})
with self.assertRaises(EvidenceIntegrityError):
manifest.replace_artifact(
artifact="a", replacement_sha256="1" * 64, reason="", replaced_at="now"
)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,58 @@
from __future__ import annotations
import sys
import unittest
from dataclasses import replace
from pathlib import Path
APP = Path(__file__).resolve().parents[2] / "active-runtime" / "app"
sys.path.insert(0, str(APP))
from aios_incubator.worktree_governance import (
WorktreeRecord,
WorktreeRegistry,
WorktreeState,
)
def record(**values) -> WorktreeRecord:
defaults = dict(
path="/data/worktrees/task-1",
owner="codex",
task_id="task-1",
branch="task/one",
base_oid="a" * 40,
current_oid="a" * 40,
)
defaults.update(values)
return WorktreeRecord(**defaults)
class WorktreeGovernanceTests(unittest.TestCase):
def test_dirty_and_runtime_dirty_are_release_blocking(self) -> None:
dirty = record(dirty_count=2)
runtime = replace(dirty, active_runtime=True)
self.assertEqual(dirty.state, WorktreeState.OWNER_REVIEW_REQUIRED)
self.assertEqual(runtime.state, WorktreeState.TRUSTED_RUNTIME_DIRTY)
self.assertTrue(dirty.release_blocking)
self.assertTrue(runtime.release_blocking)
def test_locked_or_prunable_requires_cleanup(self) -> None:
self.assertEqual(record(locked=True).state, WorktreeState.STALE_CLEANUP_REQUIRED)
self.assertEqual(record(prunable=True).state, WorktreeState.STALE_CLEANUP_REQUIRED)
def test_registry_refuses_dirty_archive_and_lists_blockers(self) -> None:
registry = WorktreeRegistry((record(dirty_count=1),))
self.assertEqual(len(registry.release_blockers()), 1)
with self.assertRaises(ValueError):
registry.mark_archived("/data/worktrees/task-1", "b" * 40)
def test_clean_record_can_be_archived(self) -> None:
registry = WorktreeRegistry((record(),))
archived = registry.mark_archived("/data/worktrees/task-1", "b" * 40)
self.assertEqual(archived.state, WorktreeState.ARCHIVED)
self.assertFalse(archived.release_blocking)
if __name__ == "__main__":
unittest.main()