new direction
This commit is contained in:
parent
e3e4d1823d
commit
74beb526e9
24 changed files with 795 additions and 397 deletions
10
README.md
10
README.md
|
|
@ -1,6 +1,7 @@
|
|||
# patch.moi
|
||||
|
||||
Feed watching and flow dispatch service for upstream project events.
|
||||
Git-first maintenance control plane for custom patches on top of upstream open
|
||||
source software.
|
||||
|
||||
Canonical public host: `https://patch.moi`.
|
||||
|
||||
|
|
@ -10,7 +11,12 @@ This is a Bun monorepo:
|
|||
|
||||
- `apps/patch`: the Patch service, feed poller, JSONL store, Discord output,
|
||||
and flow dispatch adapter.
|
||||
- `docs`: Tome documentation site published under `/docs`.
|
||||
- `docs`: Tome documentation site for patch.moi.
|
||||
|
||||
patch.moi treats Git as the source of truth for maintained projects. Upstream
|
||||
and fork remotes, patch branches, tags, and commits describe the patch stack.
|
||||
Patch records update intake, dispatch attempts, and operational history around
|
||||
those Git facts.
|
||||
|
||||
## Endpoints
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,91 @@
|
|||
---
|
||||
title: Architecture
|
||||
description: How feeds, targets, state, and flow dispatch fit together.
|
||||
description: How upstream intake, Git state, forge service mode, workspaces, and release channels fit together.
|
||||
---
|
||||
|
||||
# Architecture
|
||||
|
||||
Patch has three runtime pieces:
|
||||
patch.moi has three product responsibilities:
|
||||
|
||||
1. Notice upstream movement.
|
||||
2. Start or resume the right maintenance workflow.
|
||||
3. Keep enough durable state to inspect, retry, and review what happened.
|
||||
|
||||
The Git repository remains the source of truth for the maintained project.
|
||||
patch.moi does not replace remotes, branches, tags, commits, or release refs
|
||||
with a separate project file. It reads those facts and records operational state
|
||||
around them.
|
||||
|
||||
## Runtime Pieces
|
||||
|
||||
The current service has these runtime pieces:
|
||||
|
||||
- The HTTP server exposes health and admin flow endpoints.
|
||||
- The feed poller reads configured upstream feeds on an interval.
|
||||
- The JSONL store keeps feed signals, fork-sync jobs, flow events, and dispatch
|
||||
outcomes under `DATA_DIR`.
|
||||
- The JSONL store keeps feed signals, flow events, and dispatch outcomes under
|
||||
`DATA_DIR`.
|
||||
- The flow client can execute locally or dispatch to an HTTP flow backend.
|
||||
|
||||
The poller does not know how to complete product-specific work. It only turns a
|
||||
feed entry into a normalized signal and follows the target configured for that
|
||||
source.
|
||||
Those pieces are the intake layer. The patch-stack layer can run in local mode
|
||||
against a checkout, or in service mode through a remote forge workflow and
|
||||
runner.
|
||||
|
||||
Flow targets create a generic `FlowEvent` and use the shared flow client. That
|
||||
client gives Patch the same contract in local development and in HTTP-backed
|
||||
service mode.
|
||||
The first concrete repo to model against is `../codex`. Its maintained branch is
|
||||
`code-mode-exec-hooks` in the Peezy fork, and the branch carries Code Mode and
|
||||
Peezy npm release patches ahead of `origin/main`.
|
||||
|
||||
## Maintenance Loop
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["upstream release, tag, or branch update"] --> B["Patch FeedSignal"]
|
||||
B --> C["durable update event"]
|
||||
C --> D{"mode"}
|
||||
D -- local --> E["local Codex workspace"]
|
||||
D -- service --> R["remote forge workflow"]
|
||||
R --> S["runner checkout"]
|
||||
E --> F["rebase or replay patch commits"]
|
||||
S --> F
|
||||
F --> G{"conflicts or failing checks?"}
|
||||
G -- yes --> H["PR, issue, or paused intervention"]
|
||||
G -- no --> I["candidate branch or tag"]
|
||||
I --> J["internal build channel"]
|
||||
I --> K["public release channel"]
|
||||
```
|
||||
|
||||
## Local Mode
|
||||
|
||||
In local mode, patch.moi can run inside or next to the maintained repository.
|
||||
The repository itself describes the project:
|
||||
|
||||
- `upstream` or another configured remote points at the source project.
|
||||
- `origin` or another fork remote points at the maintained fork.
|
||||
- branch names identify the maintained patch stack and candidate refs.
|
||||
- tags identify upstream release points and downstream release candidates.
|
||||
|
||||
No `.patchmoi` file is required for that topology.
|
||||
|
||||
## Service Mode
|
||||
|
||||
In service mode, the forge is the coordination surface. For Codex maintenance,
|
||||
patch.moi should interact with the remote fork host:
|
||||
|
||||
- create or update remote maintenance branches
|
||||
- trigger forge workflows or runners
|
||||
- open or update pull requests, issues, comments, checks, and artifacts
|
||||
- record workflow run ids, branch names, and review links
|
||||
|
||||
The runner checkout is disposable. The durable project state is the remote fork,
|
||||
its refs, and the forge records around the maintenance attempt.
|
||||
|
||||
For the Codex fork, service mode should be able to target a remote fork, fetch
|
||||
OpenAI upstream refs in a runner, rebase `code-mode-exec-hooks`, and push a
|
||||
candidate branch or `rust-v*` tag when policy allows.
|
||||
|
||||
See [Forge service mode](forge-service-mode).
|
||||
|
||||
## Boundaries
|
||||
|
||||
patch.moi owns update intake and maintenance orchestration. Local workspaces or
|
||||
forge runners own the actual patch application work. Release channels own
|
||||
deployment and publishing decisions.
|
||||
|
|
|
|||
126
docs/pages/concepts/codex-fork-model.md
Normal file
126
docs/pages/concepts/codex-fork-model.md
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
---
|
||||
title: Codex fork model
|
||||
description: The concrete Git topology patch.moi should learn from the neighboring Codex fork.
|
||||
---
|
||||
|
||||
# Codex Fork Model
|
||||
|
||||
The neighboring `../codex` checkout is the concrete model for patch.moi concept
|
||||
development. It shows why patch.moi should treat Git as the project source of
|
||||
truth and keep Patch state focused on orchestration.
|
||||
|
||||
## Observed Repository
|
||||
|
||||
Observed on 2026-05-16:
|
||||
|
||||
| Fact | Value |
|
||||
| --- | --- |
|
||||
| Checkout | `../codex` |
|
||||
| Current branch | `code-mode-exec-hooks` |
|
||||
| Fork remote | `origin` -> `https://github.com/peezy-tech/codex` |
|
||||
| Branch tracking | `origin/code-mode-exec-hooks` |
|
||||
| Comparison branch | `origin/main` |
|
||||
| Patch branch head | `f8594cf39` |
|
||||
| Candidate tag at head | `rust-v0.130.0` |
|
||||
| Local working tree | untracked `codex-rs/code-mode/TYPECHECK_PLAN.md` |
|
||||
|
||||
There is no `upstream` remote configured in this checkout. That is an important
|
||||
setup case for patch.moi: the CLI or service should detect it and offer to add
|
||||
`https://github.com/openai/codex.git` as the upstream remote before running a
|
||||
release maintenance workflow.
|
||||
|
||||
## Patch Stack
|
||||
|
||||
The maintained patch stack is the commits on `code-mode-exec-hooks` ahead of
|
||||
`origin/main`:
|
||||
|
||||
```text
|
||||
5e0d6c54e Expose Code Mode exec to hooks
|
||||
d715d5829 Add native code mode replay action
|
||||
a2fb3e6c9 Publish peezy codex npm packages
|
||||
bc03f1afa Use fork-friendly Peezy npm release workflow
|
||||
74e1540e1 Increase release build timeout
|
||||
f8594cf39 Use peezy.tech npm scope
|
||||
```
|
||||
|
||||
Those commits are the patch inventory. patch.moi should not duplicate them in a
|
||||
project file. It should read them from Git and record the runs that attempted to
|
||||
carry them forward.
|
||||
|
||||
## What This Teaches patch.moi
|
||||
|
||||
The Codex fork makes the desired model concrete:
|
||||
|
||||
- `origin/main` is a useful local comparison baseline, but a real upstream
|
||||
remote is still needed for canonical release tags.
|
||||
- `code-mode-exec-hooks` is the maintained patch branch, but internal use is
|
||||
not simply "run from this branch."
|
||||
- `rust-v0.130.0` at the branch head is a downstream candidate or release tag.
|
||||
- the npm package rename to `@peezy.tech/*` is part of the patch stack, not a
|
||||
Patch service setting.
|
||||
- the public release path is encoded in `.github/workflows/rust-release.yml`.
|
||||
- the internal release surface should build the native binary, place it in the
|
||||
npm wrapper's local vendor layout, and use a Bun link workflow so the local
|
||||
`codex` command exercises the same JavaScript launcher path as a release.
|
||||
- a dirty or untracked working tree should block automated rebases until the
|
||||
operator decides whether that local work belongs in the patch stack.
|
||||
|
||||
## Maintenance Workspace
|
||||
|
||||
A patch application workspace for this repo should do the normal Git work:
|
||||
|
||||
```bash
|
||||
cd ../codex
|
||||
git status --short --branch
|
||||
git remote get-url origin
|
||||
git remote get-url upstream || git remote add upstream https://github.com/openai/codex.git
|
||||
git fetch upstream --tags --prune
|
||||
git fetch origin --prune
|
||||
git rev-list --oneline origin/main..code-mode-exec-hooks
|
||||
```
|
||||
|
||||
For an upstream release event, the workspace can resolve the upstream tag,
|
||||
rebase `code-mode-exec-hooks`, run Codex-specific checks, and push a candidate
|
||||
branch or tag when policy allows.
|
||||
|
||||
In service mode, that work should be triggered through the remote fork host. For
|
||||
example, patch.moi can create or update a maintenance branch on GitHub, trigger
|
||||
a runner, and let that runner perform the checkout, rebase, build, and push. The
|
||||
local `../codex` checkout is a model for topology and local validation, not the
|
||||
service's durable execution surface.
|
||||
|
||||
## Feature Workspace
|
||||
|
||||
Feature development should happen in a separate workspace or branch. A new
|
||||
custom feature starts from the current maintained branch, produces commits, and
|
||||
only becomes part of the maintained patch stack after it is intentionally merged
|
||||
or rebased into `code-mode-exec-hooks`.
|
||||
|
||||
## Channel Split
|
||||
|
||||
The same candidate ref can serve different channels:
|
||||
|
||||
| Channel | Codex fork example |
|
||||
| --- | --- |
|
||||
| Internal use | build the local native binary, stage it into the npm wrapper/vendor shape, and link that package with Bun |
|
||||
| Public release | push `rust-v*` tags and let GitHub Actions publish `@peezy.tech/*` packages |
|
||||
|
||||
Internal use should be close to the actual release surface without requiring the
|
||||
full multiplatform CI release. The useful local loop is:
|
||||
|
||||
```bash
|
||||
cd ../codex
|
||||
# Codex's Rust workspace lives under codex-rs.
|
||||
(cd codex-rs && cargo build -p codex-cli --bin codex)
|
||||
mkdir -p codex-cli/vendor/x86_64-unknown-linux-musl/codex
|
||||
cp codex-rs/target/debug/codex codex-cli/vendor/x86_64-unknown-linux-musl/codex/codex
|
||||
(cd codex-cli && bun link)
|
||||
bun link @peezy.tech/codex
|
||||
codex --version
|
||||
```
|
||||
|
||||
This example shows the x64 Linux wrapper path. The exact target directory,
|
||||
target triple, and global-versus-project link choice can vary by host and
|
||||
validation target, but the principle is stable: test the npm wrapper plus native
|
||||
binary handoff locally, then leave multiplatform artifacts and trusted npm
|
||||
publishing to CI.
|
||||
38
docs/pages/concepts/codex-use-case.md
Normal file
38
docs/pages/concepts/codex-use-case.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
title: Codex use case
|
||||
description: How patch.moi applies to Codex fork maintenance.
|
||||
---
|
||||
|
||||
# Codex Use Case
|
||||
|
||||
patch.moi watches GitHub OpenAI Codex branch and release feeds. Branch activity
|
||||
can notify operators. Release activity can emit a generic `upstream.release`
|
||||
flow event for codex-flow automation.
|
||||
|
||||
The concrete local model is the neighboring `../codex` checkout:
|
||||
|
||||
- `origin` points at `https://github.com/peezy-tech/codex`.
|
||||
- `code-mode-exec-hooks` is the maintained patch branch.
|
||||
- `origin/main` is the current comparison branch.
|
||||
- `rust-v0.130.0` is a downstream tag on the maintained branch head.
|
||||
- the patch stack contains Code Mode exec/replay work and Peezy npm release
|
||||
changes.
|
||||
|
||||
That checkout currently lacks an `upstream` remote, so a patch.moi setup flow
|
||||
should add or confirm `https://github.com/openai/codex.git` before a release
|
||||
rebase.
|
||||
|
||||
The Codex maintenance flow rebases the Peezy Codex fork patch stack onto a
|
||||
canonical upstream release tag. That is a patch application workspace, not a
|
||||
public release by itself.
|
||||
|
||||
Internal Codex use can track a fast-moving branch for local work. Public npm
|
||||
release can follow upstream release tags and trusted publishing. Those channels
|
||||
should share candidate Git refs when appropriate, but one should not block the
|
||||
other by default.
|
||||
|
||||
In service mode, the same Codex maintenance work can run through a forge runner:
|
||||
patch.moi creates or updates the remote maintenance branch, triggers the runner,
|
||||
and records the resulting branch, artifact, check, or PR.
|
||||
|
||||
See [Codex fork model](codex-fork-model) for the exact repo-derived model.
|
||||
|
|
@ -1,17 +1,43 @@
|
|||
---
|
||||
title: Flow boundary
|
||||
description: What Patch owns and what codex-flow packages own.
|
||||
description: What patch.moi owns, what codex-flow owns, and where gateway-style workspace orchestration belongs.
|
||||
---
|
||||
|
||||
# Flow boundary
|
||||
|
||||
Patch owns upstream observation. It knows about feeds, source ids, feed state,
|
||||
and dispatch attempts.
|
||||
patch.moi owns upstream observation and patch-stack orchestration. It knows
|
||||
about feed sources, update signals, maintained repositories, remote branches,
|
||||
workflow runs, dispatch attempts, and operator-visible state.
|
||||
|
||||
codex-flow owns execution. Flow packages match `FlowEvent.type` and payload
|
||||
schema, run Bun or gated Code Mode steps, and emit `FLOW_RESULT`.
|
||||
codex-flow owns portable event execution. Flow packages match `FlowEvent.type`
|
||||
and payload schema, run Bun or Code Mode steps, and emit `FLOW_RESULT`.
|
||||
|
||||
Product completion stays outside Patch. For example, OpenAI Codex release
|
||||
automation should decide how to update a fork, open a branch, ask for review, or
|
||||
publish a result. Patch only dispatches the upstream release event and records
|
||||
the dispatch outcome.
|
||||
The boundary should stay narrow:
|
||||
|
||||
| Layer | Owns |
|
||||
| --- | --- |
|
||||
| patch.moi intake | feeds, source ids, feed state, update records |
|
||||
| patch.moi orchestration | maintained repo selection, remote branch policy, workflow triggers, retry and review state |
|
||||
| codex-flow | generic event matching, step execution, run state, `FLOW_RESULT` |
|
||||
| local workspace or forge runner | git operations, conflict resolution, checks, candidate refs |
|
||||
| release channel | deploy, publish, trusted publishing, rollback policy |
|
||||
|
||||
## Flow Events Are Triggers
|
||||
|
||||
A generic `upstream.release` event is a good trigger. It should not become the
|
||||
whole product model.
|
||||
|
||||
patch.moi should be able to say: this upstream release produced this workflow
|
||||
run, which produced this candidate branch, which was used by this internal build
|
||||
or public release. A single flow event cannot hold that lifecycle cleanly.
|
||||
|
||||
## Service Backend
|
||||
|
||||
A patch.moi service backend is useful when patch.moi needs to coordinate a
|
||||
remote forge, human intervention, and operator surfaces. That backend can own
|
||||
patch.moi-specific service state while still using codex-flow for generic event
|
||||
execution where it fits.
|
||||
|
||||
The rule is simple: use flow events for portable automation triggers, and use a
|
||||
patch.moi backend for patch-stack product state: remote refs, workflow runs,
|
||||
pull requests, issues, checks, artifacts, and review status.
|
||||
|
|
|
|||
85
docs/pages/concepts/forge-service-mode.md
Normal file
85
docs/pages/concepts/forge-service-mode.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
---
|
||||
title: Forge service mode
|
||||
description: How patch.moi should coordinate remote fork maintenance through a forge and its runners.
|
||||
---
|
||||
|
||||
# Forge Service Mode
|
||||
|
||||
Service mode should be forge-oriented. patch.moi should interact with the
|
||||
remote Git host for the maintained Codex fork and let that forge hold the
|
||||
durable coordination surface.
|
||||
|
||||
In this mode, patch.moi is not a daemon babysitting one long-lived local clone.
|
||||
It watches upstream, updates remote refs, opens or updates review surfaces,
|
||||
triggers workflow runners, and records enough state to inspect what happened.
|
||||
|
||||
## Remote Surface
|
||||
|
||||
A forge-oriented service can use these remote objects as the product surface:
|
||||
|
||||
| Remote object | Purpose |
|
||||
| --- | --- |
|
||||
| fork repository | durable maintained project |
|
||||
| upstream mirror or remote metadata | source of upstream refs and tags |
|
||||
| patch branch | maintained patch stack |
|
||||
| maintenance branch | candidate branch for one upstream update |
|
||||
| pull request or issue | review and operator discussion |
|
||||
| workflow run | disposable execution workspace |
|
||||
| artifacts | internal build output and logs |
|
||||
| checks or statuses | policy gate for landing or publishing |
|
||||
|
||||
Git refs and forge records are durable. Runner workspaces are temporary.
|
||||
|
||||
## Service Flow
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["upstream update detected"] --> B["patch.moi records update"]
|
||||
B --> C["create or update remote maintenance branch"]
|
||||
C --> D["trigger forge workflow or runner"]
|
||||
D --> E["runner checks out fork and upstream"]
|
||||
E --> F["runner rebases patch stack"]
|
||||
F --> G["runner builds, tests, and writes artifacts"]
|
||||
G --> H["push candidate ref and report status"]
|
||||
H --> I["patch.moi updates PR or issue"]
|
||||
I --> J{"policy allows landing?"}
|
||||
J -- yes --> K["merge, tag, or publish internal artifact"]
|
||||
J -- no --> L["wait for review or intervention"]
|
||||
```
|
||||
|
||||
## Codex Fork Shape
|
||||
|
||||
For Codex maintenance, patch.moi should treat the remote fork as the service
|
||||
backend:
|
||||
|
||||
- keep `peezy-tech/codex` as the maintained fork repository
|
||||
- create patch and maintenance branches in that repository
|
||||
- trigger GitHub Actions or another registered runner
|
||||
- let the runner create or update patch commits
|
||||
- publish internal artifacts from runner output when policy allows
|
||||
- use PRs, issues, comments, checks, and artifacts as the operator surface
|
||||
|
||||
The service can still keep its own feed cursor and run index, but the important
|
||||
project state should be recoverable from the remote forge.
|
||||
|
||||
## Difference From Local Mode
|
||||
|
||||
Local mode is checkout-oriented. The operator is near the repo and can run,
|
||||
build, link, inspect, and fix directly.
|
||||
|
||||
Service mode is remote-oriented. patch.moi talks to the forge, and the forge
|
||||
runner creates disposable checkouts to do the work. This keeps service
|
||||
automation closer to how releases, review, CI, and artifacts already work.
|
||||
|
||||
## Codex Runner Role
|
||||
|
||||
Codex can participate inside the runner:
|
||||
|
||||
- resolve or rebase patch conflicts
|
||||
- update package metadata
|
||||
- run project-specific verification
|
||||
- leave structured failure context for review
|
||||
- push a candidate branch when allowed
|
||||
|
||||
That Codex execution is part of the workflow job. It does not need to be a
|
||||
long-lived workspace owned by the patch.moi service process.
|
||||
|
|
@ -1,260 +0,0 @@
|
|||
---
|
||||
title: Forgejo forking problem space
|
||||
description: Historical analysis for tracking and possibly forking Forgejo from Patch signals.
|
||||
---
|
||||
|
||||
# Forgejo Forking Problem Space
|
||||
|
||||
Date: 2026-05-12
|
||||
|
||||
## Current Setup
|
||||
|
||||
Created a jojo.build mirror:
|
||||
|
||||
- Repo: https://jojo.build/peezy-tech/jojo
|
||||
- SSH: `ssh://git@jojo.build/peezy-tech/jojo.git`
|
||||
- Upstream: `https://codeberg.org/forgejo/forgejo.git`
|
||||
- Default branch: `forgejo`
|
||||
- Mirror interval: `8h`
|
||||
|
||||
This is currently a mirror, not a working fork branch. That is a good starting
|
||||
point for source inspection and tracking upstream movement. It is not yet a good
|
||||
place for custom patches, because mirror updates are expected to follow upstream.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Forking Forgejo is feasible, but it is not a small maintenance commitment.
|
||||
Forgejo is a full Go web application with a substantial frontend build,
|
||||
database migrations, templates, Actions integration, SSH/HTTP Git serving,
|
||||
packages, OAuth2, and admin surfaces. A fork is reasonable only if the desired
|
||||
customization cannot be achieved through supported configuration, OIDC, reverse
|
||||
proxy auth, static assets, or template overrides.
|
||||
|
||||
For SIWE specifically, the preferred order remains:
|
||||
|
||||
1. Use SIWE through an external OpenID Connect provider.
|
||||
2. Use a trusted reverse proxy that performs SIWE and passes identity headers.
|
||||
3. Fork Forgejo only if we need first-class SIWE UX or native account semantics.
|
||||
|
||||
## Upstream Release Cadence
|
||||
|
||||
Forgejo stable releases are published quarterly. LTS releases are published in
|
||||
the first quarter of each year and receive critical bugfix/security support for
|
||||
one year and three months. The current LTS line is v15.0, released 2026-04-16
|
||||
and supported until 2027-07-15.
|
||||
|
||||
Implication: a fork has to either:
|
||||
|
||||
- Track every quarterly release and absorb breaking changes often.
|
||||
- Track only LTS releases and accept slower access to new Forgejo features.
|
||||
- Track upstream `forgejo` continuously, which maximizes merge churn.
|
||||
|
||||
For a production instance, an LTS-based fork is the most conservative option.
|
||||
|
||||
## What A Fork Would Own
|
||||
|
||||
At minimum, a maintained fork owns:
|
||||
|
||||
- A source branch policy.
|
||||
- CI for Go, frontend, templates, linting, and tests.
|
||||
- Binary or container image builds.
|
||||
- A release/version naming scheme.
|
||||
- Security patch intake.
|
||||
- Upgrade rehearsals against jojo.build data.
|
||||
- Documentation for local patches.
|
||||
- A rollback path to upstream Forgejo.
|
||||
|
||||
The risky areas are not only code conflicts. They are also database migrations,
|
||||
template changes, auth/session behavior, Actions behavior, and generated assets.
|
||||
|
||||
## Build And Test Surface
|
||||
|
||||
Forgejo source includes:
|
||||
|
||||
- `go.mod` for the backend.
|
||||
- `package.json` and `webpack.config.js` for frontend assets.
|
||||
- `Makefile` for build/test targets.
|
||||
- `Dockerfile` and `Dockerfile.rootless`.
|
||||
- Published release notes in `release-notes-published/`.
|
||||
|
||||
Official build docs require Go, Node.js/npm, and `make`. Older docs mention Go
|
||||
1.22+ and Node 20+, but we should verify exact versions from the branch we pin
|
||||
before building production artifacts.
|
||||
|
||||
Initial local validation target should be:
|
||||
|
||||
```bash
|
||||
make help
|
||||
make deps-frontend
|
||||
make frontend
|
||||
make test
|
||||
make build
|
||||
```
|
||||
|
||||
Exact target names need confirmation from the current Makefile before scripting.
|
||||
|
||||
## Auth Extension Surface
|
||||
|
||||
Forgejo has configurable auth sources:
|
||||
|
||||
- Local database auth.
|
||||
- LDAP via BindDN.
|
||||
- LDAP simple auth.
|
||||
- SMTP.
|
||||
- PAM.
|
||||
- OAuth2.
|
||||
- OpenID Connect.
|
||||
- OpenID.
|
||||
- Reverse proxy header auth.
|
||||
|
||||
From source inspection, auth source types are compiled into the application.
|
||||
OAuth2 providers are registered in Go during init via an internal Goth provider
|
||||
registry. That registry is useful for patching Forgejo, but it is not an
|
||||
external plugin API.
|
||||
|
||||
Native SIWE would likely require one of these approaches:
|
||||
|
||||
- Add a first-class OAuth2/OIDC provider if SIWE is presented as OIDC.
|
||||
- Add a custom auth flow and routes for EIP-4361 challenge/signature handling.
|
||||
- Add account-linking fields for wallet addresses and ENS-derived display data.
|
||||
- Add admin settings and migration(s) if wallet addresses become persisted
|
||||
first-class identities.
|
||||
|
||||
The more native the SIWE behavior, the more the fork touches security-critical
|
||||
surface: sessions, CSRF, account linking, auto-registration, 2FA bypass rules,
|
||||
and recovery flows.
|
||||
|
||||
## SIWE Fork Design Questions
|
||||
|
||||
Before writing code, resolve these:
|
||||
|
||||
- Is an Ethereum address the canonical Forgejo username, an external account
|
||||
identifier, or merely a linked credential?
|
||||
- Do users need email addresses?
|
||||
- Can a wallet create a new Forgejo account automatically?
|
||||
- How are lost wallets handled?
|
||||
- Can one Forgejo account link multiple wallets?
|
||||
- Is ENS only display metadata, or does it influence identity?
|
||||
- Are smart-contract wallets/EIP-1271 required?
|
||||
- Which chains are accepted?
|
||||
- Does SIWE bypass local 2FA, complement it, or become a second factor?
|
||||
- How do Git over HTTPS, SSH keys, access tokens, and API auth map to wallet
|
||||
sign-in?
|
||||
|
||||
These questions matter more than the login button. Forgejo identity is used by
|
||||
Git, issues, packages, Actions, API tokens, and admin permissions.
|
||||
|
||||
## Fork Strategies
|
||||
|
||||
### Strategy A: No Fork
|
||||
|
||||
Use config, OIDC, reverse proxy auth, and supported UI customization.
|
||||
|
||||
Best for:
|
||||
|
||||
- Branding.
|
||||
- Trusted SIWE/OIDC experiment.
|
||||
- Avoiding security patch ownership.
|
||||
|
||||
Risk:
|
||||
|
||||
- Less native UX.
|
||||
- Identity model constrained by Forgejo's existing auth flows.
|
||||
|
||||
### Strategy B: Patch Branch On LTS
|
||||
|
||||
Create a branch like `jojo/v15.0` from the current LTS tag, maintain a minimal
|
||||
patch stack, and periodically rebase or merge v15.0 patch releases.
|
||||
|
||||
Best for:
|
||||
|
||||
- Production stability.
|
||||
- Small, well-contained changes.
|
||||
- Predictable security patch intake.
|
||||
|
||||
Risk:
|
||||
|
||||
- Larger jumps when moving to the next LTS.
|
||||
- Backport work if desired features land in newer stable releases.
|
||||
|
||||
### Strategy C: Patch Branch On Upstream `forgejo`
|
||||
|
||||
Maintain `jojo/forgejo` on top of upstream development.
|
||||
|
||||
Best for:
|
||||
|
||||
- Contributing changes upstream.
|
||||
- Early access to Forgejo improvements.
|
||||
|
||||
Risk:
|
||||
|
||||
- Highest churn.
|
||||
- Bad fit for production unless we have strong CI and staging.
|
||||
|
||||
### Strategy D: Hard Product Fork
|
||||
|
||||
Rename/rebrand deeply, ship independent releases, and diverge freely.
|
||||
|
||||
Best for:
|
||||
|
||||
- Building a distinct forge product.
|
||||
|
||||
Risk:
|
||||
|
||||
- Largest maintenance burden.
|
||||
- Security, release, migration, and support responsibilities become ours.
|
||||
|
||||
This should be avoided unless jojo.build becomes a product-level Forgejo
|
||||
distribution.
|
||||
|
||||
## Recommended Path
|
||||
|
||||
Use the mirror as the upstream intake point. Do not customize the mirror branch.
|
||||
|
||||
Next create a working fork branch only when we have a concrete patch to test:
|
||||
|
||||
- `jojo/v15.0` from the latest v15.0.x tag for production-minded patches.
|
||||
- `jojo/forgejo` from upstream `forgejo` for exploratory upstreamable patches.
|
||||
|
||||
For SIWE, first prototype without a Forgejo fork:
|
||||
|
||||
1. Configure a SIWE OIDC provider against a test Forgejo instance.
|
||||
2. Test user creation, account linking, logout, API tokens, Git over HTTPS, and
|
||||
SSH key management.
|
||||
3. Separately test reverse proxy header auth with a toy trusted auth service.
|
||||
4. Only fork if those approaches fail on essential UX or identity semantics.
|
||||
|
||||
## Maintenance Checklist For Any Fork
|
||||
|
||||
- Track upstream release notes and security announcements.
|
||||
- Keep a patch inventory with rationale and owner.
|
||||
- Rebase/merge upstream into a staging branch first.
|
||||
- Run full build and test suite.
|
||||
- Run upgrade rehearsal against a copy of production data.
|
||||
- Smoke test login, repo browsing, Git SSH, Git HTTPS, Actions, packages,
|
||||
mirrors, and admin pages.
|
||||
- Keep a rollback artifact for the previous known-good binary/container.
|
||||
- Document every app.ini setting required by the fork.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Is jojo.build currently installed from binary, container, package manager, or
|
||||
local build?
|
||||
- How is production deployment currently rolled out and rolled back?
|
||||
- Do we want custom patches to be private indefinitely, or upstreamable?
|
||||
- Would SIWE be required for all users, optional, or only for selected orgs?
|
||||
- Is the target experience "login with wallet" or broader onchain identity?
|
||||
- Are we willing to run an external IdP such as a SIWE OIDC provider?
|
||||
|
||||
## Sources Consulted
|
||||
|
||||
- Forgejo mirror created from `https://codeberg.org/forgejo/forgejo.git`.
|
||||
- Forgejo auth docs: https://forgejo.org/docs/v11.0/user/authentication/
|
||||
- Forgejo OAuth2 provider docs: https://forgejo.org/docs/v13.0/user/oauth2-provider/
|
||||
- Forgejo customization docs: https://forgejo.org/docs/next/admin/advanced/customization/
|
||||
- Forgejo config cheat sheet: https://forgejo.org/docs/latest/admin/config-cheat-sheet/
|
||||
- Forgejo upgrade guide: https://forgejo.org/docs/next/admin/upgrade/
|
||||
- Forgejo release schedule: https://forgejo.org/docs/v11.0/admin/release-schedule
|
||||
- Forgejo compile-from-source docs: https://forgejo.org/docs/v7.0/developer/from-source/
|
||||
- SIWE docs: https://docs.siwe.xyz/
|
||||
- SIWE hosted OIDC docs: https://docs.login.xyz/servers/oidc-provider/hosted-oidc-provider
|
||||
107
docs/pages/concepts/git-source-of-truth.md
Normal file
107
docs/pages/concepts/git-source-of-truth.md
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
---
|
||||
title: Git source of truth
|
||||
description: Why patch.moi uses remotes, branches, tags, and commits as the project model.
|
||||
---
|
||||
|
||||
# Git Source Of Truth
|
||||
|
||||
patch.moi should not invent a second project format for patch stacks. The
|
||||
maintained repository is already the best source of truth:
|
||||
|
||||
- remotes say where upstream and the maintained fork live
|
||||
- branches say which patch stack is being maintained
|
||||
- tags say which upstream or downstream release point is being targeted
|
||||
- commits are the patch inventory
|
||||
- worktrees, checkouts, and runner workspaces are disposable execution surfaces
|
||||
|
||||
This matters because patch.moi is meant to maintain open source forks, not hide
|
||||
them behind an application database.
|
||||
|
||||
## Required Facts
|
||||
|
||||
A maintained project needs these facts to be discoverable from Git:
|
||||
|
||||
| Fact | Typical expression |
|
||||
| --- | --- |
|
||||
| Upstream project | `upstream` remote |
|
||||
| Maintained fork | `origin` remote |
|
||||
| Upstream release point | upstream tag or branch |
|
||||
| Patch stack | commits on a maintained branch ahead of upstream |
|
||||
| Candidate output | downstream branch or tag |
|
||||
|
||||
Names can be configured by the operator or service, but the facts should still
|
||||
resolve to Git refs.
|
||||
|
||||
## What patch.moi Stores
|
||||
|
||||
patch.moi stores operational state:
|
||||
|
||||
- feed cursors
|
||||
- normalized upstream signals
|
||||
- dispatched flow events
|
||||
- dispatch outcomes
|
||||
- workspace run status
|
||||
- retry and replay history
|
||||
- operator-facing notes or intervention state
|
||||
|
||||
That state explains what happened. It is not the patch stack itself.
|
||||
|
||||
## Local Mode
|
||||
|
||||
When patch.moi runs locally, the current checkout can be the project model. The
|
||||
CLI or service process should inspect remotes and branches, then add missing
|
||||
remotes only when the operator confirms or supplied enough information.
|
||||
|
||||
The default happy path is:
|
||||
|
||||
```bash
|
||||
git remote get-url upstream
|
||||
git remote get-url origin
|
||||
git branch --show-current
|
||||
git fetch upstream --tags --prune
|
||||
```
|
||||
|
||||
If the upstream remote is missing, patch.moi can help add it. If the fork remote
|
||||
is missing, patch.moi can help point `origin` or another chosen remote at the
|
||||
maintained fork.
|
||||
|
||||
A cloned GitHub fork commonly starts with only `origin` set to the user's fork.
|
||||
That is a valid initial shape. patch.moi can use provider metadata to discover
|
||||
the parent repository, then materialize that discovery into Git by adding an
|
||||
`upstream` remote and fetching tags.
|
||||
|
||||
The neighboring Codex fork demonstrates this exact case. `../codex` has
|
||||
`origin` set to `https://github.com/peezy-tech/codex` and a maintained
|
||||
`code-mode-exec-hooks` branch, but no `upstream` remote. patch.moi should infer
|
||||
the patch stack from Git and treat the missing upstream remote as setup work.
|
||||
|
||||
See [Codex fork model](codex-fork-model) for the concrete topology.
|
||||
|
||||
## Service Mode
|
||||
|
||||
When patch.moi runs as a service, the remote forge becomes the durable
|
||||
coordination surface. The service should talk to remote repositories, branches,
|
||||
pull requests, issues, workflow runs, checks, and artifacts.
|
||||
|
||||
Runner checkouts are disposable. A workflow can clone the fork, fetch upstream,
|
||||
rebase the patch stack, build artifacts, push a candidate branch, and disappear.
|
||||
|
||||
The important rule stays the same: pushed refs and forge records are durable
|
||||
truth; runner workspace state is temporary execution state.
|
||||
|
||||
See [Forge service mode](forge-service-mode).
|
||||
|
||||
## Policy That Is Not In Git
|
||||
|
||||
Some policy cannot be inferred from refs alone:
|
||||
|
||||
- which feed to watch
|
||||
- which branch should receive patch-stack updates
|
||||
- which checks are required before a candidate is usable
|
||||
- which ref supplies the internal build/link workflow
|
||||
- which forge workflow or runner should apply patches
|
||||
- whether public release uses GitHub trusted publishing
|
||||
|
||||
That policy can live in service configuration, environment, codex-flow config,
|
||||
or existing repo-native files such as `package.json`, CI workflows, `Makefile`,
|
||||
or release docs. It should not obscure where the patch stack actually lives.
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
title: Upstream use cases
|
||||
description: How Patch is used for Forgejo and Codex upstream tracking.
|
||||
---
|
||||
|
||||
# Upstream use cases
|
||||
|
||||
## Forgejo
|
||||
|
||||
Patch watches Codeberg Forgejo branch and release feeds. Branch activity can be
|
||||
notification-only. Release activity can still produce a legacy `fork_sync` job
|
||||
for a jojo-hosted Forgejo fork workflow.
|
||||
|
||||
The Forgejo fork remains a maintenance decision outside Patch. Patch records the
|
||||
upstream signal and job; fork policy, branch policy, CI, and release ownership
|
||||
belong to the Forgejo fork process.
|
||||
|
||||
## OpenAI Codex
|
||||
|
||||
Patch watches GitHub OpenAI Codex branch and release feeds. Branch activity can
|
||||
notify operators. Release activity emits a generic `upstream.release` flow event
|
||||
for codex-flow automation.
|
||||
|
||||
This keeps the release feed integration stable while the actual Codex release
|
||||
automation evolves in flow packages and backends.
|
||||
110
docs/pages/concepts/workspaces-and-channels.md
Normal file
110
docs/pages/concepts/workspaces-and-channels.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
title: Workspaces and channels
|
||||
description: How update scanning, patch application, feature development, internal builds, and public releases differ.
|
||||
---
|
||||
|
||||
# Workspaces And Channels
|
||||
|
||||
patch.moi has to keep several concepts separate. They often touch the same Git
|
||||
repository, but they should not collapse into one process.
|
||||
|
||||
## Update Feed
|
||||
|
||||
The update feed watches upstream. It answers one question:
|
||||
|
||||
> Did upstream move in a way we care about?
|
||||
|
||||
That can be a release tag, a branch update, a security advisory, or another
|
||||
source signal. The feed should create durable update records and then stop. It
|
||||
does not decide how to deploy or publish the maintained fork.
|
||||
|
||||
## Patch Application Workspace
|
||||
|
||||
A patch application workspace is the disposable place where a specific upstream
|
||||
point is carried forward into the maintained patch stack. In local mode, that
|
||||
can be a Codex workspace near the checkout. In service mode, it should usually
|
||||
be a forge runner checkout.
|
||||
|
||||
Typical work:
|
||||
|
||||
- fetch upstream and fork remotes
|
||||
- resolve the upstream target tag or commit
|
||||
- rebase, merge, or cherry-pick the patch stack
|
||||
- stop on conflicts with useful context
|
||||
- run verification commands
|
||||
- produce a candidate branch or tag
|
||||
|
||||
The workspace may be local or runner-managed. The patch stack itself still lives
|
||||
in Git.
|
||||
|
||||
In the current Codex fork, this means carrying the commits on
|
||||
`code-mode-exec-hooks` ahead of `origin/main` onto a canonical upstream release
|
||||
tag from `openai/codex`.
|
||||
|
||||
## Feature Development Workspace
|
||||
|
||||
A feature development workspace creates new patch commits. It is not the same as
|
||||
the maintenance workspace or runner job.
|
||||
|
||||
Feature work can start from the current maintained branch, produce commits, and
|
||||
push them to a patch branch or pull request. Once merged into the maintained
|
||||
patch stack, those commits become part of future maintenance runs.
|
||||
|
||||
Keeping feature development separate prevents a new feature from being confused
|
||||
with the automated task of carrying existing patches onto a new upstream point.
|
||||
|
||||
## Internal Build Channel
|
||||
|
||||
The internal channel is for immediate use by the operator. For example:
|
||||
|
||||
- a local Codex fork can build and link the native binary through the npm wrapper
|
||||
- a runner can publish internal Codex artifacts from a maintenance branch
|
||||
- internal containers or binaries may be produced before public release
|
||||
|
||||
This channel can track upstream main, a release candidate branch, or any other
|
||||
operator-chosen ref. It should not be blocked by public release mechanics unless
|
||||
the operator wants that coupling.
|
||||
|
||||
For the Codex fork, the internal channel should build the local native binary,
|
||||
stage it into the npm wrapper/vendor layout, and link that package with Bun.
|
||||
That tests the same JavaScript launcher and binary handoff users get from npm
|
||||
without waiting for the full multiplatform CI release.
|
||||
|
||||
In service mode, the same idea should happen through a forge runner artifact:
|
||||
the runner builds the binary, stages the wrapper shape, and publishes an
|
||||
internal artifact or package without invoking the whole public release workflow.
|
||||
|
||||
## Public Release Channel
|
||||
|
||||
The public release channel is for artifacts other people consume. It usually has
|
||||
stricter rules:
|
||||
|
||||
- follow upstream release tags
|
||||
- run reproducible CI checks
|
||||
- publish from the public repository
|
||||
- use GitHub Actions or another trusted publishing path for npm
|
||||
- keep release notes and versioning stable
|
||||
|
||||
Public release can take longer than internal use. A clean architecture lets
|
||||
internal builds move while public release waits for review, CI, or upstream
|
||||
release cadence.
|
||||
|
||||
For the Codex fork, public release is the `rust-v*` tag path in GitHub Actions
|
||||
that publishes the `@peezy.tech/*` npm packages. That path should remain
|
||||
separate from local use of the fork.
|
||||
|
||||
## Why This Split Matters
|
||||
|
||||
The same upstream signal may fan out to multiple outcomes:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Update["upstream update"] --> Apply["patch application workspace"]
|
||||
Apply --> Candidate["candidate ref"]
|
||||
Candidate --> Internal["internal build"]
|
||||
Candidate --> Public["public release"]
|
||||
Candidate --> Feature["future feature branch base"]
|
||||
```
|
||||
|
||||
patch.moi should record the relationship between those outcomes without forcing
|
||||
one channel to depend on another.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Configure feed sources
|
||||
description: Add upstream feeds and choose notification, fork-sync, or flow targets.
|
||||
description: Add upstream feeds and route update signals into patch maintenance work.
|
||||
---
|
||||
|
||||
# Configure feed sources
|
||||
|
|
@ -8,6 +8,9 @@ description: Add upstream feeds and choose notification, fork-sync, or flow targ
|
|||
Feed sources live in a JSON file referenced by `FEED_SOURCES_PATH`. The bundled
|
||||
file is `apps/patch/feed-sources.json`.
|
||||
|
||||
Feed sources describe intake. They should not duplicate the maintained patch
|
||||
stack. The patch stack lives in Git as remotes, branches, tags, and commits.
|
||||
|
||||
## Choose an event
|
||||
|
||||
Use `event: "push"` for branch commit feeds and `event: "release"` for release
|
||||
|
|
@ -15,7 +18,7 @@ feeds. Patch normalizes both into `FeedSignal` records.
|
|||
|
||||
## Choose a target
|
||||
|
||||
`notify_only` stores the signal and can notify Discord:
|
||||
`notify_only` stores the signal without dispatching patch work:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -26,17 +29,6 @@ feeds. Patch normalizes both into `FeedSignal` records.
|
|||
}
|
||||
```
|
||||
|
||||
`fork_sync` stores a legacy fork-sync job for release entries:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": "jojo",
|
||||
"repoFullName": "peezy-tech/jojo",
|
||||
"branch": "forgejo",
|
||||
"mode": "fork_sync"
|
||||
}
|
||||
```
|
||||
|
||||
`flow_dispatch` creates a generic `FlowEvent` and dispatches it:
|
||||
|
||||
```json
|
||||
|
|
@ -51,5 +43,9 @@ feeds. Patch normalizes both into `FeedSignal` records.
|
|||
}
|
||||
```
|
||||
|
||||
For patch-stack maintenance, prefer `flow_dispatch` to create an
|
||||
`upstream.release` or `upstream.update` trigger. Let the receiving workspace read
|
||||
Git to discover the maintained patch branch and candidate refs.
|
||||
|
||||
Set `primeOnly: false` only when old feed entries should be emitted on the first
|
||||
poll.
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
title: Enable Discord output
|
||||
description: Send selected upstream signals to a Discord webhook.
|
||||
---
|
||||
|
||||
# Enable Discord output
|
||||
|
||||
Discord notifications are disabled by default.
|
||||
|
||||
```bash
|
||||
DISCORD_OUTPUT_ENABLED=true
|
||||
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
|
||||
DISCORD_NOTIFY_EVENTS=push,release
|
||||
```
|
||||
|
||||
`DISCORD_NOTIFY_EVENTS` is a comma-separated allow list. Patch still stores feed
|
||||
signals when Discord is disabled or when an event is not in the allow list.
|
||||
|
||||
Notifications include provider, repository, event type, branch, author, short
|
||||
SHA, queued job kind, and source id when those fields are available.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Run Patch locally
|
||||
description: Install dependencies, start the service, and run checks.
|
||||
description: Install dependencies, inspect the Git project model, start the service, and run checks.
|
||||
---
|
||||
|
||||
# Run Patch locally
|
||||
|
|
@ -11,6 +11,29 @@ Install from the repository root:
|
|||
bun install
|
||||
```
|
||||
|
||||
Inspect the maintained repository you want patch.moi to operate around. The
|
||||
repo should expose its upstream and fork as Git remotes:
|
||||
|
||||
```bash
|
||||
git remote -v
|
||||
git branch --show-current
|
||||
git status --short --branch
|
||||
```
|
||||
|
||||
The usual local shape is:
|
||||
|
||||
| Git fact | Meaning |
|
||||
| --- | --- |
|
||||
| `upstream` remote | source project |
|
||||
| `origin` remote | maintained fork |
|
||||
| current branch | patch stack or candidate branch |
|
||||
| upstream tag | release point to rebase onto |
|
||||
|
||||
If `upstream` is missing, the repo may still be valid. A common GitHub flow is
|
||||
fork in the web UI, then clone your own fork, which gives you only `origin`.
|
||||
patch.moi should discover the parent repository from provider metadata when it
|
||||
can, then add and fetch the upstream remote.
|
||||
|
||||
Start the service app:
|
||||
|
||||
```bash
|
||||
|
|
@ -33,3 +56,11 @@ DATA_DIR=./data FEED_SOURCES_PATH=./feed-sources.json bun run dev
|
|||
```
|
||||
|
||||
`GET /healthz` returns `ok` when the server is running.
|
||||
|
||||
Local flow dispatch runs from the process working directory when
|
||||
`PATCH_FLOW_DISPATCH_URL` is unset. That makes local mode useful for testing a
|
||||
patch application workspace before sending the same event to a service backend.
|
||||
|
||||
Local mode is checkout-oriented. Service mode is forge-oriented: patch.moi
|
||||
should talk to the remote forge, trigger a runner, and let that runner perform
|
||||
the disposable checkout and patch application work.
|
||||
|
|
|
|||
|
|
@ -1,48 +1,60 @@
|
|||
---
|
||||
title: patch.moi
|
||||
description: Feed watching and flow dispatch for upstream project events.
|
||||
description: Hands-off maintenance for custom patches on top of upstream open source software.
|
||||
---
|
||||
|
||||
# patch.moi
|
||||
|
||||
Patch is a small Bun service that watches upstream Atom/RSS feeds and turns
|
||||
selected upstream activity into durable Patch records, Discord notifications,
|
||||
or generic codex-flow events.
|
||||
patch.moi keeps custom features alive on top of upstream open source projects.
|
||||
It watches upstream movement, records durable update signals, and hands the
|
||||
actual patch work to local workspaces or remote forge runners that operate on
|
||||
normal Git repositories.
|
||||
|
||||
The service keeps the product boundary narrow:
|
||||
The product boundary is Git-first:
|
||||
|
||||
- Feeds describe upstream repositories and events.
|
||||
- Patch normalizes feed entries into `FeedSignal` records.
|
||||
- Targets decide whether a signal is notification-only, a legacy fork-sync job,
|
||||
or a generic flow dispatch.
|
||||
- Flow dispatch uses `@peezy.tech/flow-runtime/client` so Patch can run flows
|
||||
locally during development or send events to an HTTP backend in service mode.
|
||||
- Admin endpoints inspect stored flow events and dispatch records, then retry or
|
||||
replay events when an upstream automation needs another attempt.
|
||||
- Upstream projects stay upstream remotes, tags, branches, and release feeds.
|
||||
- Maintained forks stay fork remotes and patch branches.
|
||||
- Patch stacks are commits, branches, and tags, not a second Patch-specific
|
||||
project file.
|
||||
- patch.moi records observations, dispatch attempts, workflow runs, and review
|
||||
state around those Git facts.
|
||||
- Local Codex workspaces or forge runners do the maintenance work: rebase patch
|
||||
commits, resolve conflicts, build candidates, and leave human intervention
|
||||
points when needed.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Feed["Atom or RSS feed"] --> Patch["Patch poller"]
|
||||
Patch --> Signal["FeedSignal JSONL"]
|
||||
Signal --> Notify["Discord output"]
|
||||
Signal --> Job["fork_sync job JSONL"]
|
||||
Signal --> Event["FlowEvent JSONL"]
|
||||
Event --> Client["flow-runtime client"]
|
||||
Client --> Local["local flow execution"]
|
||||
Client --> Backend["HTTP flow backend"]
|
||||
Upstream["upstream repo"] --> Feed["release and branch feeds"]
|
||||
Upstream --> Git["upstream remote"]
|
||||
Fork["maintained fork"] --> Git
|
||||
Feed --> Patch["patch.moi intake"]
|
||||
Patch --> Event["durable update signal"]
|
||||
Event --> Workspace["local workspace or forge runner"]
|
||||
Git --> Workspace
|
||||
Workspace --> Candidate["remote candidate branch, tag, or artifact"]
|
||||
Candidate --> Internal["internal build channel"]
|
||||
Candidate --> Public["public release channel"]
|
||||
```
|
||||
|
||||
## Start here
|
||||
|
||||
- New service setup: [Watch an upstream release](tutorials/watch-upstream-release).
|
||||
- Codex release automation: [Dispatch a Codex release flow](tutorials/dispatch-codex-release-flow).
|
||||
- Codex patch-stack automation: [Dispatch a Codex release flow](tutorials/dispatch-codex-release-flow).
|
||||
- Running the service: [Run Patch locally](guides/run-patch-locally).
|
||||
- Git model: [Git source of truth](concepts/git-source-of-truth).
|
||||
- Concrete Codex model: [Codex fork model](concepts/codex-fork-model).
|
||||
- Service mode: [Forge service mode](concepts/forge-service-mode).
|
||||
- Release channels: [Workspaces and channels](concepts/workspaces-and-channels).
|
||||
- Exact feed shape: [Feed sources](reference/feed-sources).
|
||||
- Admin operations: [HTTP API](reference/http-api).
|
||||
|
||||
## What is in this repo
|
||||
|
||||
- `apps/patch`: the Patch Bun service, feed poller, JSONL store, Discord output,
|
||||
and flow dispatch adapter.
|
||||
- `apps/patch`: the Patch Bun service, feed poller, JSONL store, and flow
|
||||
dispatch adapter.
|
||||
- `docs`: this Tome documentation site, organized with the Diataxis framework.
|
||||
- `Dockerfile`: container image for the Patch service app.
|
||||
|
||||
The current service implements upstream intake and dispatch. Patch-stack
|
||||
maintenance is performed by the local workspace, forge runner, or codex-flow
|
||||
package that receives the event.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
title: Dispatch and replay flow events
|
||||
description: Use local or HTTP flow execution and retry stored events.
|
||||
title: Flow event retry and replay
|
||||
description: Reference for local or HTTP flow execution and retrying stored update triggers.
|
||||
---
|
||||
|
||||
# Dispatch and replay flow events
|
||||
# Flow Event Retry And Replay
|
||||
|
||||
Patch creates deterministic event ids:
|
||||
|
||||
|
|
@ -14,6 +14,10 @@ patch:<sourceId>:<entryId>:<eventType>
|
|||
Dispatch is idempotent at the flow backend by event id. Replay intentionally
|
||||
asks the backend to create another attempt for the stored event.
|
||||
|
||||
For patch-stack maintenance, treat the event as an update trigger. The
|
||||
authoritative patch state still comes from Git when the local workspace or forge
|
||||
runner runs.
|
||||
|
||||
## Select HTTP dispatch
|
||||
|
||||
```bash
|
||||
|
|
@ -39,3 +43,7 @@ curl -X POST http://127.0.0.1:3000/flow-events/<event-id>/replay
|
|||
`retry` dispatches the stored event again. `replay` calls the backend replay
|
||||
endpoint when HTTP mode is configured, or dispatches locally when no backend URL
|
||||
is configured.
|
||||
|
||||
Retrying or replaying an event should not rewrite patch branches by itself. The
|
||||
workspace or flow package decides whether to push candidate refs after it checks
|
||||
the current Git state.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Environment
|
||||
description: Runtime environment variables used by Patch.
|
||||
description: Runtime environment variables used by patch.moi.
|
||||
---
|
||||
|
||||
# Environment
|
||||
|
|
@ -15,11 +15,14 @@ description: Runtime environment variables used by Patch.
|
|||
| `PATCH_FLOW_DISPATCH_URL` | unset | Default flow backend URL for dispatch targets. |
|
||||
| `PATCH_FLOW_BACKEND_URL` | unset | Alternate default backend base URL. |
|
||||
| `PATCH_FLOW_DISPATCH_SECRET` | unset | HMAC secret for HTTP flow dispatch. |
|
||||
| `DISCORD_OUTPUT_ENABLED` | `false` | Enables Discord webhook output. |
|
||||
| `DISCORD_WEBHOOK_URL` | unset | Discord webhook target. |
|
||||
| `DISCORD_NOTIFY_EVENTS` | `push,release` | Comma-separated notification allow list. |
|
||||
| `CODEX_APP_SERVER_CODEX_COMMAND` | unset | Passed to local code-mode flow execution. |
|
||||
| `CODEX_HOME` | unset | Passed to local code-mode flow execution. |
|
||||
|
||||
Feed target fields can override backend settings with `dispatchUrl`,
|
||||
`dispatchUrlEnv`, and `dispatchSecretEnv`.
|
||||
|
||||
Git topology is intentionally not represented here. Local mode should read
|
||||
upstream, fork, branch, and tag state from Git. Service mode should read remote
|
||||
repository, branch, workflow, and review state from the forge. Environment
|
||||
variables should stay limited to runtime concerns such as dispatch URLs, data
|
||||
directories, and Codex execution settings.
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
---
|
||||
title: Feed sources
|
||||
description: JSON schema by convention for upstream feed configuration.
|
||||
description: JSON schema by convention for upstream update intake.
|
||||
---
|
||||
|
||||
# Feed sources
|
||||
|
||||
`FEED_SOURCES_PATH` points at a JSON object with a `sources` array.
|
||||
|
||||
This file configures update intake, not the patch stack. A flow target can add
|
||||
payload hints, but the receiving workspace should use Git remotes, branches, and
|
||||
tags as the maintained project source of truth.
|
||||
|
||||
```ts
|
||||
type FeedSourceConfig = {
|
||||
id: string;
|
||||
provider: "codeberg" | "github" | "jojo";
|
||||
provider: "github";
|
||||
url: string;
|
||||
event: "push" | "release";
|
||||
repo: {
|
||||
|
|
@ -20,7 +24,7 @@ type FeedSourceConfig = {
|
|||
webUrl: string;
|
||||
defaultBranch?: string;
|
||||
};
|
||||
target?: FeedForkSyncTarget | FeedFlowDispatchTarget;
|
||||
target?: FeedFlowDispatchTarget;
|
||||
pollIntervalSeconds?: number;
|
||||
primeOnly?: boolean;
|
||||
};
|
||||
|
|
@ -42,3 +46,7 @@ type FeedFlowDispatchTarget = {
|
|||
The flow payload includes provider, event, source id, entry id, title, URL,
|
||||
author, published time, repository fields, ref, SHA, tag, and raw feed metadata.
|
||||
Values from `target.payload` are merged last.
|
||||
|
||||
For release maintenance, use a stable event type such as `upstream.release` and
|
||||
include only routing hints in `payload`. Avoid copying branch topology into the
|
||||
feed source when it can be read from the repository.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: HTTP API
|
||||
description: Health, flow event inspection, retry, replay, and dispatch history.
|
||||
description: Health, update-trigger inspection, retry, replay, and dispatch history.
|
||||
---
|
||||
|
||||
# HTTP API
|
||||
|
|
@ -25,6 +25,9 @@ POST /flow-events/:id/replay
|
|||
The list endpoint returns stored events newest first. The detail endpoint
|
||||
returns the event and matching dispatch records.
|
||||
|
||||
These endpoints inspect update triggers and dispatch attempts. They do not
|
||||
inspect or modify Git patch stacks directly.
|
||||
|
||||
## Dispatches
|
||||
|
||||
```text
|
||||
|
|
|
|||
|
|
@ -1,19 +1,24 @@
|
|||
---
|
||||
title: JSONL state
|
||||
description: Files written under DATA_DIR.
|
||||
description: Operational records written under DATA_DIR.
|
||||
---
|
||||
|
||||
# JSONL state
|
||||
|
||||
Patch uses append-only JSONL files for durable service records.
|
||||
Patch uses append-only JSONL files for durable service records. These files are
|
||||
operational state. They are not the patch stack.
|
||||
|
||||
| File | Contents |
|
||||
| --- | --- |
|
||||
| `feed-state.json` | Per-source last seen entry and last checked timestamp. |
|
||||
| `feed-events.jsonl` | Normalized `FeedSignal` records. |
|
||||
| `feed-jobs.jsonl` | Legacy `fork_sync` jobs emitted from release signals. |
|
||||
| `flow-events.jsonl` | Generic `FlowEvent` records emitted by flow targets. |
|
||||
| `flow-dispatches.jsonl` | Dispatch, retry, replay, and failure records. |
|
||||
|
||||
Admin endpoints read `flow-events.jsonl` and `flow-dispatches.jsonl`. The feed
|
||||
poller appends to all relevant files as it accepts new feed entries.
|
||||
|
||||
If a runner checkout is lost, patch.moi should be able to recreate the
|
||||
maintenance context from remote Git refs and forge records. JSONL state explains
|
||||
feed and dispatch history; Git and the forge remain the source of truth for
|
||||
patch contents and review state.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Packages
|
||||
description: Workspace packages in the Patch monorepo.
|
||||
description: Workspace packages in the patch.moi monorepo.
|
||||
---
|
||||
|
||||
# Packages
|
||||
|
|
@ -15,10 +15,12 @@ Responsibilities:
|
|||
- Poll configured feeds.
|
||||
- Normalize entries into `FeedSignal` records.
|
||||
- Store JSONL state.
|
||||
- Emit optional Discord notifications.
|
||||
- Dispatch generic codex-flow events through `@peezy.tech/flow-runtime/client`.
|
||||
- Serve admin inspection, retry, and replay endpoints.
|
||||
|
||||
The service package does not store patch contents. Maintained patch stacks live
|
||||
in Git repositories operated on by local workspaces or forge runners.
|
||||
|
||||
## `@peezy.tech/patch-docs`
|
||||
|
||||
The Tome documentation package in `docs`. Build it with:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
---
|
||||
title: Dispatch a Codex release flow
|
||||
description: Connect the OpenAI Codex release feed to codex-flow automation.
|
||||
description: Connect the OpenAI Codex release feed to a Codex patch-stack maintenance workspace.
|
||||
---
|
||||
|
||||
# Dispatch a Codex release flow
|
||||
|
||||
Patch was built to let upstream release activity trigger generic codex-flow
|
||||
automation without putting Codex-specific completion logic into Patch itself.
|
||||
This tutorial connects upstream OpenAI Codex releases to the Codex fork
|
||||
maintenance flow. The flow rebases a maintained patch stack onto an upstream
|
||||
release tag and verifies the candidate.
|
||||
|
||||
## 1. Use the release source
|
||||
|
||||
|
|
@ -14,6 +15,24 @@ The bundled `apps/patch/feed-sources.json` includes
|
|||
`github-openai-codex-releases`. Its target emits `upstream.release` events with
|
||||
the upstream repository and release tag in the payload.
|
||||
|
||||
The maintained Codex fork should still be modeled in Git. In the neighboring
|
||||
`../codex` checkout, `origin` is `https://github.com/peezy-tech/codex` and
|
||||
`code-mode-exec-hooks` is the maintained patch branch.
|
||||
|
||||
Before running release maintenance, make sure the checkout has a canonical
|
||||
upstream remote:
|
||||
|
||||
```bash
|
||||
cd ../codex
|
||||
git remote get-url upstream || git remote add upstream https://github.com/openai/codex.git
|
||||
git fetch upstream --tags --prune
|
||||
git fetch origin --prune
|
||||
git status --short --branch
|
||||
```
|
||||
|
||||
If `git status` shows local changes or untracked files, resolve them before an
|
||||
automated rebase.
|
||||
|
||||
## 2. Point Patch at a backend
|
||||
|
||||
```bash
|
||||
|
|
@ -38,7 +57,26 @@ or `X-Patch-Admin-Token: <token>`.
|
|||
|
||||
## 4. Keep completion app-owned
|
||||
|
||||
Patch dispatches the generic event. The installed Codex release flow owns the
|
||||
work that happens next: matching `flow.toml`, running steps, checking gates, and
|
||||
emitting `FLOW_RESULT`. Product-specific completion stays in that flow package
|
||||
or its backend worker.
|
||||
Patch dispatches the generic event. The installed Codex release flow or
|
||||
workspace owns the work that happens next:
|
||||
|
||||
- fetch upstream tags
|
||||
- resolve the release tag
|
||||
- rebase the maintained patch branch
|
||||
- collect conflict context when the rebase stops
|
||||
- run the configured checks
|
||||
- optionally push a candidate ref
|
||||
|
||||
That candidate can be used for an internal build/link workflow before a public
|
||||
release exists: build the local native binary, place it in the npm wrapper's
|
||||
vendor layout, and link the package with Bun. Public npm publishing should stay
|
||||
a separate channel because it may need GitHub Actions, trusted publishing,
|
||||
release review, and upstream schedule alignment.
|
||||
|
||||
For the current Codex fork, public release is the `rust-v*` tag workflow that
|
||||
publishes the `@peezy.tech/*` npm packages.
|
||||
|
||||
In service mode, patch.moi should trigger this work through the remote forge
|
||||
instead of depending on a persistent local checkout. The service creates or
|
||||
updates a maintenance branch, starts a runner workflow, and records the PR,
|
||||
issue, check, artifact, or candidate ref that the runner produces.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,22 @@
|
|||
---
|
||||
title: Watch an upstream release
|
||||
description: Configure a release feed and store the first Patch flow event.
|
||||
description: Configure a release feed and turn an upstream release into patch maintenance input.
|
||||
---
|
||||
|
||||
# Watch an upstream release
|
||||
|
||||
This tutorial creates the smallest useful release watcher: one upstream release
|
||||
feed that becomes a stored `upstream.release` flow event.
|
||||
This tutorial creates the smallest useful patch.moi intake: one upstream release
|
||||
feed that becomes a stored update signal. That signal can later start a Codex
|
||||
workspace that rebases a patch stack.
|
||||
|
||||
Before configuring the feed, make sure the maintained repository has a Git
|
||||
source of truth:
|
||||
|
||||
```bash
|
||||
git remote get-url upstream
|
||||
git remote get-url origin
|
||||
git status --short --branch
|
||||
```
|
||||
|
||||
## 1. Add a feed source
|
||||
|
||||
|
|
@ -42,7 +52,10 @@ Create or edit `apps/patch/feed-sources.json`:
|
|||
}
|
||||
```
|
||||
|
||||
## 2. Start Patch
|
||||
The target emits a generic `upstream.release` event. The event is a trigger for
|
||||
patch work; the patch commits still live in the maintained Git repository.
|
||||
|
||||
## 2. Start patch.moi
|
||||
|
||||
```bash
|
||||
DATA_DIR=./data \
|
||||
|
|
@ -63,3 +76,17 @@ When the feed later contains an unseen release entry, Patch appends:
|
|||
|
||||
If `PATCH_FLOW_DISPATCH_URL` is not set, Patch uses local flow execution from
|
||||
the working directory. If it is set, Patch sends the event to the HTTP backend.
|
||||
|
||||
## 4. Connect patch work
|
||||
|
||||
A matching codex-flow package or backend workspace can consume the
|
||||
`upstream.release` event and run the maintenance loop:
|
||||
|
||||
1. fetch upstream tags
|
||||
2. resolve the release tag
|
||||
3. rebase or replay patch commits
|
||||
4. stop for conflicts or failing checks
|
||||
5. push a candidate branch or tag when policy allows
|
||||
|
||||
Internal builds and public release jobs can then consume the candidate ref
|
||||
independently.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/** @type {import('@tomehq/core').TomeConfig} */
|
||||
export default {
|
||||
name: "patch.moi",
|
||||
basePath: "/docs",
|
||||
basePath: "/",
|
||||
theme: {
|
||||
preset: "editorial",
|
||||
mode: "auto",
|
||||
|
|
@ -21,8 +21,6 @@ export default {
|
|||
pages: [
|
||||
"guides/run-patch-locally",
|
||||
"guides/configure-feed-sources",
|
||||
"guides/dispatch-and-replay-flow-events",
|
||||
"guides/enable-discord-output",
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -31,6 +29,7 @@ export default {
|
|||
"reference/environment",
|
||||
"reference/feed-sources",
|
||||
"reference/http-api",
|
||||
"reference/dispatch-and-replay-flow-events",
|
||||
"reference/jsonl-state",
|
||||
"reference/packages",
|
||||
],
|
||||
|
|
@ -39,9 +38,12 @@ export default {
|
|||
group: "Concepts",
|
||||
pages: [
|
||||
"concepts/architecture",
|
||||
"concepts/git-source-of-truth",
|
||||
"concepts/codex-fork-model",
|
||||
"concepts/forge-service-mode",
|
||||
"concepts/workspaces-and-channels",
|
||||
"concepts/flow-boundary",
|
||||
"concepts/upstream-use-cases",
|
||||
"concepts/forgejo-forking-problem-space",
|
||||
"concepts/codex-use-case",
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "patch-moi",
|
||||
"version": "0.1.0",
|
||||
"description": "Feed watching and flow dispatch service for patch.moi.",
|
||||
"description": "Git-first maintenance control plane for upstream patch stacks.",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"packageManager": "bun@1.3.11",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue