Define HopWeb as a prompt-native forge built on a maintainable Gitea foundation

Hop-State: A_06FN3NFQ6P95HFKCSC22JMR
Hop-Proposal: R_06FN3NF43ARPM6SBXX0F15R
Hop-Task: T_06FN3MVGY3MT82ESQ89BND0
Hop-Attempt: AT_06FN3MVGY092BFA5MR9C7EG
This commit is contained in:
Hop
2026-07-11 08:40:04 -07:00
parent 5da8983cb6
commit dd2c0abfd2
3 changed files with 296 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
# HopWeb
HopWeb is a collaborative forge for prompt-native software development.
It uses Git for durable source storage and Gitea for the proven forge substrate,
but makes Hop's workflow the primary product model:
- a **task** captures the outcome someone wants;
- a **prompt state** records each instruction in its causal context;
- an **attempt** is an isolated line of human or agent work;
- a **checkpoint** freezes the exact tree that was evaluated;
- **evidence** records checks against that immutable checkpoint;
- a **proposal** is a reviewable candidate outcome; and
- an **accepted state** is the current shared truth.
The product thesis is simple:
> GitHub organizes collaboration around commits and pull requests. HopWeb
> organizes human-agent collaboration around intent, attempts, evidence, and
> accepted outcomes.
## Foundation
Gitea supplies the expensive, mature infrastructure we should not rebuild:
- Git transport, repositories, LFS, and permissions
- users, organizations, teams, OAuth, and access tokens
- issues, notifications, webhooks, releases, packages, and Actions
- administration, audit surfaces, and deployment primitives
Hop supplies the differentiating control plane and experience:
- prompt and state graph persistence
- task and attempt orchestration
- agent identity and attribution
- checkpoint-bound validation evidence
- proposal review and acceptance semantics
- a Hop-native repository, task, attempt, and review interface
See [the product blueprint](docs/product-blueprint.md) and
[the Gitea foundation decision](docs/adr/0001-gitea-as-forge-foundation.md).
## First release
The first useful release is not a complete GitHub clone. It is a private,
single-installation forge where a user can:
1. create or import a repository;
2. open a task with a prompt;
3. launch one or more isolated agent attempts;
4. watch states, diffs, and checks appear live;
5. compare proposals by outcome and evidence; and
6. accept one proposal into the repository's shared state.
Everything else should be inherited from Gitea until the Hop workflow proves
that it needs a different abstraction.
@@ -0,0 +1,69 @@
# ADR 0001: Use Gitea as the forge foundation
- Status: Accepted
- Date: 2026-07-11
## Context
HopWeb needs reliable Git hosting, repository permissions, users and
organizations, review primitives, webhooks, CI integration, packages, releases,
and administration. Rebuilding this foundation would delay the Hop-native
workflow and create a large security and maintenance burden.
Gitea is a mature, MIT-licensed, Go-based forge with a REST API, OAuth2 provider,
webhooks, Git LFS, package registries, and a production-capable Actions system.
It supports custom assets, themes, templates, and repository tabs, which are
enough to prototype a unified Hop experience without immediately carrying a
large source fork.
## Decision
Use a pinned upstream Gitea release as the forge substrate. Build Hop as a
separate control-plane service and Hop-native web experience that integrates
with Gitea through stable APIs, webhooks, OAuth, and Git protocols.
Adopt a staged customization policy:
1. configuration, branding, templates, assets, and API integration;
2. small upstreamable extension points where integration seams are missing;
3. a shallow maintained fork only for essential Hop-native behavior.
Hop domain data will live outside the Gitea schema. Cross-service operations
will use stable IDs, idempotency keys, and explicit reconciliation rather than
distributed database writes.
## Consequences
### Positive
- The team can focus on Hop's state model and collaboration experience.
- Standard Git clients and familiar forge features work from the beginning.
- Gitea security fixes and features can be consumed from upstream.
- A separable control plane makes the Hop model portable to another Git host.
### Costs and risks
- A visually unified product must compose two service boundaries.
- Some acceptance operations need careful compensation and reconciliation.
- Template overrides are version-sensitive.
- A deep fork would make upstream upgrades expensive.
- Public multi-tenant runners require a stronger isolation model than Gitea's
default trusted-runner assumptions.
## Guardrails
- Pin exact Gitea versions and test upgrades in automation.
- Keep a patch ledger for every source-level deviation from upstream.
- Never edit vendored Gitea code for branding alone.
- Prefer contributing generic extension points upstream.
- Keep the Hop control plane independently testable and deployable.
- Threat-model Git hooks, webhooks, runner registration, job tokens, and
untrusted repository content before supporting public execution.
## Revisit when
- Gitea's architecture prevents a core Hop invariant;
- the source patch set grows beyond a routinely rebaseable size;
- transactional acceptance cannot be made reliable across the boundary; or
- operating two services costs more than owning a cohesive fork.
+170
View File
@@ -0,0 +1,170 @@
# HopWeb product blueprint
## Product position
HopWeb is not "Gitea with AI buttons." It is a forge whose source of truth is a
causal record of intent and verified outcomes, with Git underneath for universal
tool compatibility.
The core screen should answer four questions without reconstructing them from a
commit history:
1. What outcome was requested?
2. Who or what tried to produce it?
3. What exact result was checked, and what passed?
4. Which outcome became shared truth, and why?
## Concept mapping
| Conventional forge | HopWeb primary concept | Notes |
| --- | --- | --- |
| Issue | Task | Outcome plus its evolving prompt history |
| Branch/worktree | Attempt | Isolated work by a human, agent, or team |
| Commit | Checkpoint/state | Immutable tree plus causal parents and metadata |
| CI status | Evidence | Bound to the exact checkpoint that was tested |
| Pull request | Proposal | Candidate outcome with intent, evidence, and diff |
| Merge | Accept/land | Advances the accepted state after validation |
| Commit graph | State graph | Includes prompts, checkpoints, proposals, and outcomes |
| Contributor | Actor | Human or agent identity with attribution and policy |
Git branches, commits, and pull requests remain available as compatibility
views. They should not dictate the Hop-native experience.
## System shape
```mermaid
flowchart LR
UI["Hop-native web UI"] --> API["Hop control-plane API"]
API --> HDB["Hop state and evidence store"]
API --> ORCH["Attempt orchestrator"]
ORCH --> RUN["Isolated agent runners"]
API --> GAPI["Gitea API and webhooks"]
GAPI --> GIT["Git repositories"]
GAPI --> FORGE["Identity, permissions, issues, Actions, packages"]
RUN --> GIT
RUN --> HDB
```
### Ownership boundary
**Gitea owns** repositories, Git protocol, blob storage, users, organizations,
teams, baseline authorization, webhooks, Actions, releases, and packages.
**Hop owns** tasks, prompts, attempts, state graph edges, agent sessions,
checkpoints, evidence, proposals, acceptance policy, and orchestration.
**The Hop UI composes both.** A user should experience one product even when the
data comes from two services.
## Integration strategy
Start from an unmodified, pinned Gitea release and integrate through its API,
webhooks, OAuth, custom templates, and custom assets. This lets us validate the
workflow while preserving straightforward upstream upgrades.
Maintain a shallow source fork only when a required experience cannot be built
cleanly through those seams—for example, a first-class state graph inside every
repository route or authorization decisions that must be transactional with Git
writes. Every fork patch must be small, isolated, tested, and documented with an
upstream issue or a reason it is intentionally Hop-specific.
Do not put Hop's domain tables directly into Gitea's database. Services may
share stable identifiers, but each service owns its schema and migrations.
## Primary experience
### Repository home
Lead with active tasks, recent accepted outcomes, running attempts, and failing
evidence. Files and commits remain one click away, not the default narrative.
### Task page
Show the current requested outcome, prompt history, constraints, linked issues,
all attempts, and the policy required for acceptance.
### Attempt page
Stream agent activity and expose the evolving state graph, working diff,
checkpoints, check results, cost/runtime metadata, and interventions from humans.
### Proposal review
Review by outcome first: summary, behavioral changes, evidence, risks, then file
diff. Let reviewers compare multiple proposals for the same task side by side.
### Acceptance
Acceptance is a named product event. It advances the repository's accepted Hop
state, records the actor and policy decision, and materializes the corresponding
Git change atomically or fails without advancing either view.
## Initial domain model
- `repositories`: link a Hop repository to its Gitea repository identifier.
- `tasks`: requested outcome, status, creator, and acceptance policy.
- `states`: immutable typed nodes with tree identity, digest, actor, and time.
- `state_edges`: ordered, role-labelled causal relationships between states.
- `attempts`: isolated execution contexts associated with a task and base state.
- `checks`: commands or policies evaluated against an immutable checkpoint.
- `evidence`: normalized results, logs, artifacts, and provenance for checks.
- `proposals`: frozen candidate outcomes and their review status.
- `acceptances`: atomic record linking a proposal, accepted state, and Git ref.
- `actors`: human, service, and agent identities plus attestable metadata.
Use opaque, sortable IDs and repository-scoped uniqueness. Treat all mutable
status fields as projections of an append-only event history where auditability
matters.
## Delivery sequence
### Milestone 0 — foundation
- Pin and run Gitea locally with PostgreSQL and object storage boundaries.
- Add a Hop control-plane service and database.
- Establish Gitea OAuth/API authentication and webhook verification.
- Link Hop repositories to Gitea repositories.
- Define upgrade policy and an automated upstream rebase test.
### Milestone 1 — task to accepted outcome
- Create tasks and capture prompt states.
- Launch isolated attempts through a runner interface.
- Ingest checkpoints and checkpoint-bound check evidence.
- Freeze proposals and display their diffs.
- Accept a validated proposal and advance the Git default branch.
### Milestone 2 — native collaboration
- Multiple concurrent attempts and proposal comparison.
- Human intervention and prompt follow-ups within an attempt.
- Review policies, approvals, protected accepted state, and audit history.
- Notifications and task/attempt dashboards.
### Milestone 3 — ecosystem
- Public repositories and discoverability.
- Agent marketplace and reusable execution profiles.
- Organization policy, billing, usage controls, and hosted runners.
- GitHub/GitLab import and bidirectional compatibility workflows.
## Non-negotiable invariants
- A prompt is captured before project effects begin.
- Evidence always identifies the immutable checkpoint it evaluated.
- A proposal never changes after it is frozen.
- Acceptance never silently includes unrelated workspace effects.
- Human and agent actions are distinguishable and attributable.
- Git operations remain possible with standard Git clients.
- Hop state can be exported without requiring the HopWeb service forever.
## Decisions still to make
- Hosted SaaS, self-hosted distribution, or both for the first release.
- Runner isolation boundary: container, microVM, or pluggable backends.
- Whether accepted Hop state is encoded into Git refs/notes in addition to the
Hop database for portability and disaster recovery.
- The first authentication path: Gitea as OAuth provider or a shared external
identity provider.
- Product name: retain HopWeb internally or choose a public forge name.