From 74beb526e9a074f86e36ffa0906cd266b53c6edf Mon Sep 17 00:00:00 2001 From: matamune Date: Sat, 16 May 2026 03:20:02 +0000 Subject: [PATCH] new direction --- README.md | 10 +- docs/pages/concepts/architecture.md | 90 +++++- docs/pages/concepts/codex-fork-model.md | 126 +++++++++ docs/pages/concepts/codex-use-case.md | 38 +++ docs/pages/concepts/flow-boundary.md | 44 ++- docs/pages/concepts/forge-service-mode.md | 85 ++++++ .../concepts/forgejo-forking-problem-space.md | 260 ------------------ docs/pages/concepts/git-source-of-truth.md | 107 +++++++ docs/pages/concepts/upstream-use-cases.md | 25 -- .../pages/concepts/workspaces-and-channels.md | 110 ++++++++ docs/pages/guides/configure-feed-sources.md | 22 +- docs/pages/guides/enable-discord-output.md | 20 -- docs/pages/guides/run-patch-locally.md | 33 ++- docs/pages/index.md | 60 ++-- .../dispatch-and-replay-flow-events.md | 14 +- docs/pages/reference/environment.md | 11 +- docs/pages/reference/feed-sources.md | 14 +- docs/pages/reference/http-api.md | 5 +- docs/pages/reference/jsonl-state.md | 11 +- docs/pages/reference/packages.md | 6 +- .../tutorials/dispatch-codex-release-flow.md | 52 +++- .../pages/tutorials/watch-upstream-release.md | 35 ++- docs/tome.config.js | 12 +- package.json | 2 +- 24 files changed, 795 insertions(+), 397 deletions(-) create mode 100644 docs/pages/concepts/codex-fork-model.md create mode 100644 docs/pages/concepts/codex-use-case.md create mode 100644 docs/pages/concepts/forge-service-mode.md delete mode 100644 docs/pages/concepts/forgejo-forking-problem-space.md create mode 100644 docs/pages/concepts/git-source-of-truth.md delete mode 100644 docs/pages/concepts/upstream-use-cases.md create mode 100644 docs/pages/concepts/workspaces-and-channels.md delete mode 100644 docs/pages/guides/enable-discord-output.md rename docs/pages/{guides => reference}/dispatch-and-replay-flow-events.md (65%) diff --git a/README.md b/README.md index 310df6c..618d258 100644 --- a/README.md +++ b/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 diff --git a/docs/pages/concepts/architecture.md b/docs/pages/concepts/architecture.md index 18b23d1..70e0d8a 100644 --- a/docs/pages/concepts/architecture.md +++ b/docs/pages/concepts/architecture.md @@ -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. diff --git a/docs/pages/concepts/codex-fork-model.md b/docs/pages/concepts/codex-fork-model.md new file mode 100644 index 0000000..7223af0 --- /dev/null +++ b/docs/pages/concepts/codex-fork-model.md @@ -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. diff --git a/docs/pages/concepts/codex-use-case.md b/docs/pages/concepts/codex-use-case.md new file mode 100644 index 0000000..542996f --- /dev/null +++ b/docs/pages/concepts/codex-use-case.md @@ -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. diff --git a/docs/pages/concepts/flow-boundary.md b/docs/pages/concepts/flow-boundary.md index fa1a1b6..c950737 100644 --- a/docs/pages/concepts/flow-boundary.md +++ b/docs/pages/concepts/flow-boundary.md @@ -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. diff --git a/docs/pages/concepts/forge-service-mode.md b/docs/pages/concepts/forge-service-mode.md new file mode 100644 index 0000000..069eed3 --- /dev/null +++ b/docs/pages/concepts/forge-service-mode.md @@ -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. diff --git a/docs/pages/concepts/forgejo-forking-problem-space.md b/docs/pages/concepts/forgejo-forking-problem-space.md deleted file mode 100644 index 7655b26..0000000 --- a/docs/pages/concepts/forgejo-forking-problem-space.md +++ /dev/null @@ -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 diff --git a/docs/pages/concepts/git-source-of-truth.md b/docs/pages/concepts/git-source-of-truth.md new file mode 100644 index 0000000..265d4f9 --- /dev/null +++ b/docs/pages/concepts/git-source-of-truth.md @@ -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. diff --git a/docs/pages/concepts/upstream-use-cases.md b/docs/pages/concepts/upstream-use-cases.md deleted file mode 100644 index 673a167..0000000 --- a/docs/pages/concepts/upstream-use-cases.md +++ /dev/null @@ -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. diff --git a/docs/pages/concepts/workspaces-and-channels.md b/docs/pages/concepts/workspaces-and-channels.md new file mode 100644 index 0000000..e0489d0 --- /dev/null +++ b/docs/pages/concepts/workspaces-and-channels.md @@ -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. diff --git a/docs/pages/guides/configure-feed-sources.md b/docs/pages/guides/configure-feed-sources.md index 59b5cb9..029ee16 100644 --- a/docs/pages/guides/configure-feed-sources.md +++ b/docs/pages/guides/configure-feed-sources.md @@ -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. diff --git a/docs/pages/guides/enable-discord-output.md b/docs/pages/guides/enable-discord-output.md deleted file mode 100644 index b54aa49..0000000 --- a/docs/pages/guides/enable-discord-output.md +++ /dev/null @@ -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. diff --git a/docs/pages/guides/run-patch-locally.md b/docs/pages/guides/run-patch-locally.md index ca0ad70..f630eab 100644 --- a/docs/pages/guides/run-patch-locally.md +++ b/docs/pages/guides/run-patch-locally.md @@ -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. diff --git a/docs/pages/index.md b/docs/pages/index.md index 6557c92..b7fe2ce 100644 --- a/docs/pages/index.md +++ b/docs/pages/index.md @@ -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. diff --git a/docs/pages/guides/dispatch-and-replay-flow-events.md b/docs/pages/reference/dispatch-and-replay-flow-events.md similarity index 65% rename from docs/pages/guides/dispatch-and-replay-flow-events.md rename to docs/pages/reference/dispatch-and-replay-flow-events.md index 2587dd0..d417998 100644 --- a/docs/pages/guides/dispatch-and-replay-flow-events.md +++ b/docs/pages/reference/dispatch-and-replay-flow-events.md @@ -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::: 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//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. diff --git a/docs/pages/reference/environment.md b/docs/pages/reference/environment.md index 94b38d5..0b69809 100644 --- a/docs/pages/reference/environment.md +++ b/docs/pages/reference/environment.md @@ -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. diff --git a/docs/pages/reference/feed-sources.md b/docs/pages/reference/feed-sources.md index 65b99e6..c6cf6f2 100644 --- a/docs/pages/reference/feed-sources.md +++ b/docs/pages/reference/feed-sources.md @@ -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. diff --git a/docs/pages/reference/http-api.md b/docs/pages/reference/http-api.md index c530ae8..be7345b 100644 --- a/docs/pages/reference/http-api.md +++ b/docs/pages/reference/http-api.md @@ -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 diff --git a/docs/pages/reference/jsonl-state.md b/docs/pages/reference/jsonl-state.md index 271528b..8616446 100644 --- a/docs/pages/reference/jsonl-state.md +++ b/docs/pages/reference/jsonl-state.md @@ -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. diff --git a/docs/pages/reference/packages.md b/docs/pages/reference/packages.md index e3300c1..fe40545 100644 --- a/docs/pages/reference/packages.md +++ b/docs/pages/reference/packages.md @@ -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: diff --git a/docs/pages/tutorials/dispatch-codex-release-flow.md b/docs/pages/tutorials/dispatch-codex-release-flow.md index 4d0d775..2e33dbe 100644 --- a/docs/pages/tutorials/dispatch-codex-release-flow.md +++ b/docs/pages/tutorials/dispatch-codex-release-flow.md @@ -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: `. ## 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. diff --git a/docs/pages/tutorials/watch-upstream-release.md b/docs/pages/tutorials/watch-upstream-release.md index 66a6651..1b58041 100644 --- a/docs/pages/tutorials/watch-upstream-release.md +++ b/docs/pages/tutorials/watch-upstream-release.md @@ -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. diff --git a/docs/tome.config.js b/docs/tome.config.js index 5498c05..4b6fd51 100644 --- a/docs/tome.config.js +++ b/docs/tome.config.js @@ -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", ], }, ], diff --git a/package.json b/package.json index f520cc4..e02a869 100644 --- a/package.json +++ b/package.json @@ -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",