68d8bf2f7d
Hop-State: A_06FN69X2VW0BAXG4A4DT6V0 Hop-Proposal: R_06FN69VET1STZNKPWK913K8 Hop-Task: T_06FN637799RW5Q7WH9H6PJR Hop-Attempt: AT_06FN63779BJRBK1VFQ94GRR
215 lines
9.3 KiB
Markdown
215 lines
9.3 KiB
Markdown
# Hop agent protocol
|
|
|
|
## State graph
|
|
|
|
```text
|
|
A accepted
|
|
├─ P prompt, persisted before project effects
|
|
│ └─ C checkpoint
|
|
│ └─ R proposal
|
|
└─ P independent prompt
|
|
|
|
A + R ──land──> A next accepted state
|
|
```
|
|
|
|
State prefixes:
|
|
|
|
| Prefix | Kind | Meaning |
|
|
|---|---|---|
|
|
| `A_` | accepted | Canonical project revision |
|
|
| `P_` | prompt | Exact instruction and pre-effect context |
|
|
| `C_` | checkpoint | Immutable workspace progress |
|
|
| `R_` | proposal | Frozen candidate result |
|
|
| `F_` | failed | Durable failed execution or validation state |
|
|
| `X_` | cancelled | Durable cancelled state |
|
|
|
|
Prompt, checkpoint, and proposal states may reference identical Git trees while remaining distinct causal occurrences.
|
|
|
|
## Environment contract
|
|
|
|
| Variable | Purpose |
|
|
|---|---|
|
|
| `HOP_ROOT` | Canonical project root containing `.hop/hop.db` |
|
|
| `HOP_STATE_ID` | Prompt state authorizing the current instruction |
|
|
| `HOP_TASK_ID` | Logical task grouping related prompts and attempts |
|
|
| `HOP_ATTEMPT_ID` | Current agent approach/run |
|
|
| `HOP_WORKSPACE` | Only directory the agent may modify |
|
|
| `HOP_AGENT` | Optional runtime name used by `hop begin` when `--agent` is omitted |
|
|
|
|
Interactive agents may begin without these variables. `hop begin` returns the
|
|
equivalent IDs and workspace. Integrations should identify themselves with
|
|
`HOP_AGENT` or `--agent` and pass a stable `--session` value when available.
|
|
That session binds later messages to unfinished work; without it, each
|
|
invocation begins independent work. The Codex adapter uses `CODEX_THREAD_ID` as
|
|
the default session and `codex` as the default runtime name. Follow-ups before
|
|
acceptance continue the attempt; the first prompt after acceptance starts a
|
|
fresh task and attempt at the latest accepted state.
|
|
|
|
## Command contract
|
|
|
|
### Human or controller
|
|
|
|
```bash
|
|
hop init
|
|
hop start --agent <name> "<exact initial prompt>"
|
|
hop env <prompt-state>
|
|
hop prompt --from <state> "<exact follow-up prompt>"
|
|
hop accept <proposal> -- <final validation command>
|
|
hop sync
|
|
hop undo
|
|
```
|
|
|
|
`hop start` creates the task, attempt, prompt state, and detached workspace before returning. The controller may deliver the prompt only after exit `0`.
|
|
|
|
`hop prompt` captures a checkpoint of current workspace effects before creating the follow-up prompt state.
|
|
|
|
### Agent
|
|
|
|
POSIX shell:
|
|
|
|
```bash
|
|
hop begin --heredoc <<'HOP_PROMPT_EOF'
|
|
<exact current user message>
|
|
HOP_PROMPT_EOF
|
|
```
|
|
|
|
PowerShell:
|
|
|
|
```powershell
|
|
$hopPrompt = @'
|
|
<exact current user message>
|
|
'@
|
|
$hopPrompt | hop begin --heredoc
|
|
```
|
|
|
|
Then continue in the returned workspace:
|
|
|
|
```bash
|
|
hop state "$HOP_STATE_ID" --json
|
|
hop status --json
|
|
hop check "$HOP_STATE_ID" -- <command>
|
|
hop propose --summary "<summary>" "$HOP_STATE_ID"
|
|
hop land <proposal-state> -- <final validation command>
|
|
hop refresh <proposal-state>
|
|
```
|
|
|
|
An adapter may set `HOP_AGENT=<runtime>` or pass `--agent <runtime>`. If it has
|
|
a stable conversation/run identifier, it should also pass `--session <id>` on
|
|
every `hop begin`. Codex normally needs neither explicit flag because
|
|
`CODEX_THREAD_ID` supplies its session adapter automatically.
|
|
|
|
`hop check` snapshots the attempt and runs the command in a detached worktree materialized from that exact checkpoint. Edits made concurrently in the live workspace do not change the tested tree.
|
|
|
|
`hop propose` freezes the current nonignored workspace tree. Later workspace edits cannot change the proposal.
|
|
|
|
The initial task prompt authorizes the agent to run `hop land` after successful
|
|
validation; a second user approval is not required. Manual review is an opt-in
|
|
mode: stop at the proposal only when the user explicitly asks to review or
|
|
approve before acceptance. Validation failure, visible-root divergence,
|
|
unresolved product ambiguity, or newly required destructive/external scope
|
|
stops automatic acceptance. Path overlap and a stale accepted head do not:
|
|
Hop merges, retries, or prepares agent reconciliation.
|
|
|
|
`hop land` is the interactive working-root operation. It performs a real Git
|
|
three-way content merge, so compatible edits in the same file and identical
|
|
changes compose automatically. It validates and advances accepted state, then
|
|
safely materializes that tree into the selected visible project root. The root
|
|
must still match an accepted Hop ancestor, and ignored or untracked destination
|
|
collisions block before acceptance. Materialization uses a disposable index
|
|
and never moves HEAD, the active branch, or the user's real index.
|
|
|
|
When the three-way merge has genuine unresolved conflicts, `hop land` returns
|
|
exit `20` and automatically prepares a reconciliation prompt in the original
|
|
task but a fresh isolated attempt/workspace. Its JSON includes
|
|
`reconciliation.prompt`, `workspace`,
|
|
`conflicts`, and the proposal/current accepted states. The agent adopts that
|
|
prompt/workspace, resolves both intents, checks, proposes, and lands again.
|
|
Structural, binary, delete/rename, mode, and symlink conflicts may have no text
|
|
markers, so the agent must inspect both returned input states. Hop requires a
|
|
successful `hop check` on the resolved tree before reproposal. The user is not
|
|
asked to coordinate ordinary code conflicts. `hop refresh` is the idempotent
|
|
explicit form of the same preparation step.
|
|
|
|
`hop accept` is the controller/kernel operation. It advances SQLite and
|
|
`refs/hop/accepted` but intentionally leaves the visible root untouched.
|
|
`hop sync` safely catches a stale accepted-ancestor root up to the current
|
|
accepted state, including projects created with older Hop builds.
|
|
|
|
`hop begin` is the interactive-agent entry point. It initializes Hop when
|
|
necessary and captures the current message before the agent performs project
|
|
work. Runtime adapters identify themselves through `HOP_AGENT` or `--agent`
|
|
and use `--session` to supply a stable conversation/run key. A later
|
|
`hop begin` with the same session checkpoints the prior workspace before
|
|
appending a follow-up while that work remains unfinished. Reconciliation
|
|
transfers the session to its fresh attempt. After a proposal is accepted, the
|
|
next `hop begin` starts from the latest accepted state and never reopens the
|
|
completed workspace. Codex Desktop supplies `CODEX_THREAD_ID` as its default
|
|
session key, so its adapter does not need to add `--session` explicitly.
|
|
|
|
Pass the original message to `hop begin` without model-side redaction. Hop's
|
|
sanitizer replaces detected credential values before any durable write and
|
|
returns only typed redaction counts. Do not place the value in any later
|
|
command, summary, output, or source file.
|
|
|
|
## Exit codes
|
|
|
|
| Code | Meaning |
|
|
|---:|---|
|
|
| `0` | Success |
|
|
| `1` | Git, SQLite, filesystem, or internal error |
|
|
| `2` | Invalid CLI usage |
|
|
| `20` | Genuine three-way merge conflict; reconciliation workspace prepared |
|
|
| `21` | Accepted or attempt head changed during compare-and-swap |
|
|
| `22` | Validation command failed |
|
|
| `23` | Visible project root diverged or contains an overwrite collision |
|
|
|
|
A failed `hop check` or final landing check persists its evidence. A blocked or failed landing does not advance accepted state.
|
|
|
|
## Capture modes
|
|
|
|
### Interactive agent skill
|
|
|
|
The user types normally in their agent interface. The Hop skill makes
|
|
`hop begin` its first project action and then directs every operation into the
|
|
returned workspace. This is a pre-project-effect boundary: the runtime has
|
|
already received the prompt, but no repository inspection, command, or
|
|
modification may precede the durable prompt state. Codex Desktop is one such
|
|
adapter; it provides session continuity through `CODEX_THREAD_ID`.
|
|
|
|
### Controller-grade pre-delivery capture
|
|
|
|
```bash
|
|
hop init
|
|
hop start --agent <runtime> "Add password reset emails"
|
|
```
|
|
|
|
Use the returned workspace and environment to launch the agent. For example, conceptually:
|
|
|
|
```bash
|
|
eval "$(hop env P_...)"
|
|
<agent-command> "<the same exact prompt>"
|
|
```
|
|
|
|
The exact agent command is harness-specific. This stronger mode stores the
|
|
prompt before the model receives it. A future trusted prompt-submission hook can
|
|
provide the same boundary inside compatible agent clients.
|
|
|
|
## Failure handling
|
|
|
|
- **Missing Hop environment:** run `hop begin` before project work and use the returned state and workspace.
|
|
- **Check failure:** fix the live workspace, checkpoint/check again, then create a new proposal.
|
|
- **Review-only request:** preserve and report the proposal without landing it.
|
|
- **Frozen proposal needs changes:** record a follow-up prompt; never mutate the stored proposal.
|
|
- **Merge conflict on landing:** continue automatically in the returned
|
|
reconciliation prompt/workspace; inspect both inputs, resolve textual and
|
|
structural conflicts, validate, propose, and land again. Stop only for
|
|
product ambiguity, not ordinary textual overlap.
|
|
- **Visible-root conflict:** preserve the proposal and the user's files. Do not substitute controller-only `hop accept`; resolve or capture the visible changes, then land again.
|
|
- **Controller-accepted root is stale:** run `hop sync`; it succeeds only from an accepted ancestor and never overwrites divergence.
|
|
- **Ref inconsistency:** run `hop doctor`; use `hop doctor --repair` only outside final validation.
|
|
- **Secrets:** Hop redacts high-confidence provider keys plus contextual tokens,
|
|
passwords, private keys, authorization headers, and credential-bearing URLs
|
|
before durable storage. It also sanitizes recorded check commands/output and
|
|
proposal summaries. Detection is defense in depth, not a substitute for
|
|
environment variables or a secret manager. Never repeat a detected secret.
|