Skip to content
This repository was archived by the owner on Sep 25, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/ucf-foundation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ name: UCF foundation
on:
pull_request:
paths:
- "foundry/adapters/**"
- "foundry/contracts/transition_models.py"
- "foundry/environments/**"
- "foundry/providers/base.py"
- "foundry/storage/artifact_store.py"
- "foundry/storage/transition_journal.py"
- "foundry/verification/policy.py"
- "foundry/runtime/**"
- "foundry/orchestration/agent_runner.py"
- "foundry/orchestration/run_engine.py"
Expand Down Expand Up @@ -36,9 +40,9 @@ jobs:
run: python -m compileall -q foundry tests
- name: Lint changed foundation
run: |
ruff check foundry/contracts/transition_models.py foundry/contracts/task_types.py foundry/environments foundry/providers/base.py foundry/runtime foundry/orchestration/agent_runner.py foundry/orchestration/run_engine.py tests/unit/test_transition_models.py tests/unit/runtime/test_transition_engine.py tests/unit/orchestration/test_agent_runner.py
ruff check foundry/adapters foundry/contracts/transition_models.py foundry/contracts/task_types.py foundry/environments foundry/providers/base.py foundry/runtime foundry/storage/artifact_store.py foundry/storage/transition_journal.py foundry/verification/policy.py foundry/orchestration/agent_runner.py foundry/orchestration/run_engine.py tests/unit/test_transition_models.py tests/unit/runtime/test_transition_engine.py tests/unit/runtime/test_foundry_transition_adapter.py tests/unit/orchestration/test_agent_runner.py
- name: Test foundation
run: |
pytest -q tests/unit/test_transition_models.py tests/unit/runtime/test_transition_engine.py tests/unit/orchestration/test_agent_runner.py
pytest -q tests/unit/test_transition_models.py tests/unit/runtime/test_transition_engine.py tests/unit/runtime/test_foundry_transition_adapter.py tests/unit/orchestration/test_agent_runner.py
- name: Test full suite
run: pytest -q
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ The original Unicorn chain — **Signals → Evidence → State → Legibility**

Do not mass-rename or delete historical Foundry code merely to make terminology look generic. Generalization must be earned through exercised interfaces and tests.

When touching new UCF foundation code, prefer the contracts under `foundry/contracts/transition_models.py`, `foundry/runtime/`, `foundry/environments/`, and `foundry/providers/base.py`.
When touching new UCF foundation code, prefer `foundry/contracts/transition_models.py`, `foundry/runtime/`, `foundry/environments/`, `foundry/adapters/`, `foundry/providers/base.py`, `foundry/storage/transition_journal.py`, and `foundry/verification/policy.py`.

When touching historical Foundry code, preserve existing behavior unless the task explicitly migrates that behavior onto the new transition interfaces.
When touching historical Foundry code, preserve existing behavior unless the task explicitly migrates that behavior onto the new transition interfaces. `FoundryTransitionRuntime` is the concrete compatibility bridge; do not create a second parallel adapter path.

## Non-Negotiable Rules

Expand Down
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,17 @@ The long-term architecture should not require Claude, GitHub, source code, or Un

This repository is being reopened as UCF rather than maintained as an active Unicorn Foundry product.

A provider-neutral vNext foundation now lives alongside the historical Foundry runtime:
A provider-neutral UCF foundation now lives alongside the historical Foundry runtime:

- `IntelligenceProvider` separates orchestration from a concrete model vendor;
- `ExecutionEnvironment` separates isolated execution from Git worktrees;
- provider-neutral transition contracts represent state, evidence, actions, observations, verification, and outcomes;
- `TransitionEngine` closes a minimal state → action → observation → verification → outcome loop;
- `TransitionEngine` closes a state → action → observation → verification → outcome loop;
- `TransitionJournal` requires the verified outcome to survive the call;
- tests exercise that loop with a non-Unicorn environment and fake components.
- `FoundryTransitionRuntime` maps the historical planner, implementer, verifier, migration guard, worktree manager, and artifact store onto those interfaces;
- integration tests exercise that adapter with a real Git repository and real worktree isolation.

This does **not** mean the legacy Foundry runtime has already been generalized. `RunEngine`, verification, prompts, PR handling, persistence names, and parts of configuration remain software/Git/Claude-shaped. They will be migrated incrementally after the generic boundary is proven.
The abstraction is therefore exercised by the original machinery, not only by fakes. The remaining P0 boundary is **runtime convergence**: the backwards-compatible `RunEngine` still owns the old database/event/PR lifecycle and must delegate its core transition work to the UCF path. PR creation should become publication after an accepted transition rather than the definition of completion.

See [RETROSPECTIVE.md](RETROSPECTIVE.md) for the present-day interpretation, [docs/runtime-decoupling-audit.md](docs/runtime-decoupling-audit.md) for the migration map, and [docs/architecture.md](docs/architecture.md) for the original Foundry architecture specification.

Expand All @@ -178,9 +179,12 @@ UCf/
│ ├── runtime/
│ │ ├── interfaces.py # observer/planner/executor/verifier/journal
│ │ └── transition_engine.py # provider-neutral state-transition loop
│ ├── adapters/
│ │ └── foundry_transition.py # historical Foundry -> UCF capability bridge
│ ├── environments/
│ │ ├── base.py # ExecutionEnvironment contract
│ │ └── git_worktree.py # first concrete environment adapter
│ │ ├── git_worktree.py # concrete execution environment adapter
│ │ └── git_observer.py # explicit before/after Git state
│ ├── providers/
│ │ ├── base.py # IntelligenceProvider contract
│ │ └── claude_*.py # historical/default Claude adapters
Expand All @@ -189,7 +193,8 @@ UCf/
│ ├── git/ # historical Git/PR action surface
│ ├── tasks/ # historical Foundry task implementations
│ ├── db/ # historical run persistence
│ └── storage/ # historical artifact persistence
│ └── storage/
│ └── transition_journal.py # durable UCF outcome adapter
├── app/ # historical FastAPI control plane
├── workers/ # historical background workers
├── canon/ # historical Unicorn domain contracts
Expand Down
160 changes: 113 additions & 47 deletions docs/runtime-decoupling-audit.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,142 @@
# Runtime Decoupling Audit

This audit separates the general UCF mechanism from assumptions inherited from Unicorn Foundry.
This audit separates the general UCF mechanism from assumptions inherited from
Unicorn Foundry and records which abstractions have been exercised by real
historical machinery.

## Already generalized in this branch
## Current architecture

### Intelligence provider boundary
The repository now has three related layers:

`AgentRunner` now depends on an `IntelligenceProvider` protocol. Claude remains the default historical implementation, but the orchestration boundary no longer requires the concrete Claude provider type.
1. **UCF foundation** — provider-neutral state, evidence, action, verification,
outcome, environment, and journal contracts.
2. **Foundry adapter path** — the original Git/agent/verification/artifact
machinery running through `TransitionEngine`.
3. **Historical RunEngine** — the backwards-compatible API/database/PR lifecycle
that still owns the old `queued -> ... -> pr_opened -> completed` state machine.

### Execution target boundary
The second layer is important: the general boundary is no longer proven only by
fakes.

`TaskRequest.repo` remains named for backwards compatibility, but it is no longer restricted to `unicorn-app` or `unicorn-foundry`.
## Generalized and exercised boundaries

### Environment boundary
### Intelligence provider

`ExecutionEnvironment` defines prepare, observe-changes, and cleanup operations. `GitWorktreeEnvironment` adapts the historical worktree implementation to that interface.
`AgentRunner` depends on `IntelligenceProvider`. Claude remains the default
historical backend, but provider identity is outside the UCF runtime contract.

### Transition vocabulary
### Execution environment and observation

`foundry/contracts/transition_models.py` defines provider-neutral state snapshots, evidence references, action proposals, transition requests, observations, verification decisions, and outcomes without assuming GitHub or Unicorn.
`ExecutionEnvironment` owns workspace preparation and cleanup.
`GitWorktreeEnvironment` adapts the historical `WorktreeManager`.

### Generic transition loop
`GitStateObserver` turns an actual Git workspace into explicit state containing
HEAD, dirty status, changed files, and a diff checksum. This supplies real
before/after state to the generic loop.

`TransitionEngine` now coordinates a minimal provider-neutral loop through injected observer, planner, executor, verifier, environment, and journal capabilities. The engine does not know about Claude, GitHub, Go, TypeScript, or Unicorn.
### Transition vocabulary and engine

The historical `RunEngine` is still unchanged and Git/PR-shaped. The new engine is a parallel foundation, not a claim that migration is complete.
`TransitionEngine` coordinates:

```text
state(t)
-> plan
-> controlled action
-> observe
-> verify / independently review
-> durable outcome
-> state(t+1)
```

The engine does not know about Claude, GitHub, Go, TypeScript, Unicorn, or pull
requests.

### Historical Foundry adapters

`foundry/adapters/foundry_transition.py` maps the original capabilities onto
that loop:

| Historical capability | UCF role |
| --- | --- |
| `TaskRequest` | `TransitionRequest` input |
| `AgentRunner.run_planner` | `TransitionPlanner` |
| `AgentRunner.run_implementer` | `ActionExecutor` |
| Git worktree | `ExecutionEnvironment` |
| Git HEAD/status/diff | `StateObserver` |
| `VerificationRunner` | deterministic verification |
| blind reviewer | independent transition evaluation |
| migration guard | shared protected-path verification policy |
| `ArtifactStore` | `TransitionJournal` |
| review/verification result | `TransitionOutcome` evidence |

`REQUEST_CHANGES` remains advisory in the adapter because that is the historical
Foundry behavior. `REJECT` and deterministic verification failure reject the
transition.

### Shared safety policy

Protected-path matching and migration-guard authorization now live in
`foundry/verification/policy.py`. Both `RunEngine` and the UCF adapter use the
same policy instead of maintaining parallel copies.

### Durable continuity

`ArtifactStoreTransitionJournal` persists
`transition_outcome.json` under the transition ID before workspace cleanup.
The resulting after-state can seed the next transition.

## Evidence

The adapter integration test creates a real temporary Git repository and uses
the real `WorktreeManager` and `GitStateObserver`. It then runs planning,
implementation, verification, blind review, journaling, and cleanup through
`TransitionEngine`.

Current CI evidence for this milestone:

- 21 targeted UCF / Foundry-adapter tests pass;
- 495 full-suite tests pass;
- compile and targeted Ruff checks pass.

## Remaining historical couplings

| Coupling | Current form | General form | Migration priority |
| Coupling | Current state | Desired boundary | Priority |
| --- | --- | --- | --- |
| Lifecycle terminal | `PR_OPENED -> COMPLETED` | outcome recorded / accepted | P0 |
| Action environment | Git worktree | ExecutionEnvironment | P0 |
| Action result | Git diff + PR | environment-specific action artifact | P0 |
| Implementer role | Go / TypeScript literal | executor capability | P1 |
| Verification | Go/TS/schema commands | verifier plugins | P1 |
| Run lifecycle terminal | `PR_OPENED -> COMPLETED` still lives in `RunEngine` | verified `TransitionOutcome` defines operation result | P0 |
| Publication | PR creation is embedded in run lifecycle | publisher is post-transition / environment-specific | P0 |
| Runtime convergence | adapter path and `RunEngine` both exist | legacy engine delegates core transition work | P0 |
| Persistence | run/PR/worktree tables | transition/outcome/workspace records + legacy projection | P1 |
| Executor language | Go / TypeScript literal | executor capability selection | P1 |
| Verification | code-oriented Go/TS/schema dispatch | verifier plugins by environment/capability | P1 |
| Model routing | Claude model IDs | provider + capability routing | P1 |
| Prompt layer | coding-specific planner/implementer prompts | transition-role prompts | P1 |
| Prompts | coding-specific role prompts | environment-specific planner/executor adapters | P1 |
| Canon | Unicorn/startup schemas | environment-specific state contracts | P2 |
| Extraction | startup signal extraction | observer adapters | P2 |
| Config names | FOUNDRY, unicorn_app_* | UCF + legacy aliases | P2 |
| Persistence names | runs, PR URL, worktrees | transitions, outcomes, workspaces | P3 |
| API routes | /runs, /patches, /worktrees | /transitions, /actions, /environments | P3 |
| Config | `FOUNDRY_*`, Unicorn-era names | UCF names + compatibility aliases | P2 |
| API | `/runs`, `/patches`, `/worktrees` | transition/action/environment surfaces | P3 |

## P0 foundation status
## Next P0 milestone: converge RunEngine

The generic loop now exists alongside Foundry:
Do not delete or rename the historical state machine first. Make it a
compatibility projection over the UCF transition loop.

1. an execution environment prepares and cleans up an isolated workspace;
2. an observer establishes explicit before-state;
3. a planner proposes a provider-neutral action;
4. an executor applies the action;
5. the observer establishes after-state;
6. an independent verifier accepts or rejects the transition;
7. a journal records the verified outcome;
8. the resulting state can seed the next transition.
The next migration should:

`tests/unit/runtime/test_transition_engine.py` exercises this with a non-Unicorn environment and fake capabilities.
1. let a legacy `TaskRequest` create a UCF `TransitionRequest`;
2. delegate plan -> execute -> observe -> verify -> journal to
`FoundryTransitionRuntime`;
3. map a rejected `TransitionOutcome` into the existing failure states/events;
4. map an accepted outcome into the existing post-verification path;
5. treat PR creation as publication after an accepted transition, not as the
definition of the transition itself;
6. preserve current API responses, database rows, artifacts, and event history
while compatibility is required.

The next P0 task is **adapter migration**: make the historical Git/Claude workflow exercise these interfaces rather than maintaining a separate architectural path. In particular, `PR_OPENED -> COMPLETED` must stop being the general definition of a successful transition.
This is the point at which the two runtime paths actually converge.

## What should not be renamed yet

Do not mass-rename Foundry classes, database tables, routes, or artifact types merely to match the new vocabulary. Renaming before the generalized loop works would create churn without increasing capability.

Keep the historical runtime operational while new interfaces are introduced alongside it. Once a non-Unicorn closed loop passes end to end, migrate internals incrementally.

## Foundation boundary

The repository now contains the code-level boundary required to test UCF independently from Unicorn. Because the historical runtime is not yet routed through `TransitionEngine`, the project is currently in a dual state:

- **general UCF foundation:** provider/environment/transition interfaces plus a minimal loop;
- **historical Foundry runtime:** the working Git/PR orchestration implementation.

The next milestone is to make those two paths converge without erasing the original implementation history.
Do not mass-rename Foundry classes, database tables, routes, or artifact types
merely to match the new vocabulary. Generalization is being earned through
exercised interfaces and regression tests. Rename only when a replacement
boundary is in use.
1 change: 1 addition & 0 deletions foundry/adapters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Adapters that map historical Foundry capabilities onto UCF interfaces."""
Loading
Loading