b0c4105be3
Every GitHub write (PR, comment, review reply) must include an attribution line identifying the AI agent. Posts go out under the repository owner's account, so an unattributed post reads as the human's words. Format: _Posted by <Agent Stack> (<model>)_ Examples: - _Posted by Claude (Opus 4.5)_ - _Posted by Cursor Agent (claude-sonnet-5)_ AGENTS.md: - Added 'GitHub Attribution (Hard Rule)' section in multi-stack docs - Concrete format and examples - Clarified that a thread is not 'answered' until the reply has attribution .agents/skills/pr-watch/SKILL.md: - Added 'GitHub Attribution (Hard Rule)' subsection - Updated 'Answer substantive feedback with attribution' in obligations - Cross-references AGENTS.md for full rule context/cloud-agents.md: - Added 'GitHub Attribution (Hard Rule)' section - Same format and examples as AGENTS.md This ensures any agent reading the shared docs (Cursor, Claude, etc.) knows to attribute every GitHub write to the specific AI agent. Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
215 lines
9.1 KiB
Markdown
215 lines
9.1 KiB
Markdown
# Cloud Agents (LLM Reference)
|
|
|
|
Environment notes for agents running in cloud containers — Claude Code on the web,
|
|
Cursor cloud agents, and similar setups. Local checkouts are unaffected.
|
|
|
|
## Session Bootstrap
|
|
|
|
All agent stacks use the same bootstrap script: `scripts/agent-bootstrap.sh`. It:
|
|
|
|
1. **Seeds nix flake inputs** (GitHub tarballs are blocked; seeds over git instead)
|
|
2. Verifies the `bd` version matches the flake.nix pin
|
|
3. Installs `bd` if missing
|
|
4. Syncs the Dolt issue tracker from the git remote
|
|
5. Warms the cargo build **inside `nix develop`**
|
|
|
|
**After bootstrap, `nix develop` works.** This is the required toolchain — bare system
|
|
cargo that fails `edition2024` or missing wasm target is a misconfigured session.
|
|
|
|
**Claude Code**: `.claude/hooks/session-start.sh` calls the bootstrap automatically when
|
|
`CLAUDE_CODE_REMOTE=true`.
|
|
|
|
**Cursor cloud**: `.cursor/environment.json` runs the bootstrap via `install`. Skills are
|
|
in `.cursor/skills/` (symlinks to `.agents/skills/`).
|
|
|
|
**Other stacks**: Run `scripts/agent-bootstrap.sh` manually after checkout.
|
|
|
|
This doc is the "why", and the record of what bites when setup doesn't run.
|
|
|
|
---
|
|
|
|
## The issue tracker is not `issues.jsonl`
|
|
|
|
**`.beads/issues.jsonl` is a stale export.** It is a viewer/interchange
|
|
artifact, not the source of truth — `.beads/README.md` says as much
|
|
("Cross-machine sync and backups use Dolt remotes/backups, not JSONL
|
|
import/export"). The real tracker is the Dolt database published to
|
|
`refs/dolt/data` on the git remote.
|
|
|
|
The gap is not cosmetic. A session that hydrated from the JSONL saw 121
|
|
issues against the remote's 168, with every P1 bug showing OPEN though all
|
|
four were fixed and closed. Two beads were implemented from scratch that
|
|
the remote had recorded as closed weeks earlier, and which turned out to
|
|
be already implemented on an unmerged branch.
|
|
|
|
The hook syncs the database from the remote at session start. If it did
|
|
not run, or reported a failure:
|
|
|
|
```bash
|
|
bd list --all | wc -l # 121 means you are on the stale export
|
|
```
|
|
|
|
**Verify any bead against the code before starting it.** `git log --oneline
|
|
--all | grep -oE 'improvise-[a-z0-9]{3}'` names the ones already
|
|
referenced by a commit, and `git log origin/main` is worth a look for work
|
|
that landed without a bead reference.
|
|
|
|
---
|
|
|
|
## `bd init` is destructive here
|
|
|
|
A bare `bd init` in this repo rewrites `AGENTS.md`, `CLAUDE.md` and
|
|
`.claude/settings.json`, installs Cursor/Codex integration files, and
|
|
**commits all of it**. It also rewrites `sync.remote` in
|
|
`.beads/config.yaml`.
|
|
|
|
Always pass the opt-outs:
|
|
|
|
```bash
|
|
bd init --non-interactive --skip-agents --skip-hooks -q --remote git+<origin>
|
|
```
|
|
|
|
Even then it commits a small `.gitignore` change, so the hook runs it in a
|
|
throwaway directory and copies only `.beads/embeddeddolt` back. Do the
|
|
same if you need to re-sync by hand; never run it in the working tree.
|
|
|
|
---
|
|
|
|
## What does not work in this environment
|
|
|
|
| Thing | Status | Use instead |
|
|
|---|---|---|
|
|
| `nix develop` **without bootstrap** | Fails: flake inputs are GitHub **tarballs**, which are blocked | Bootstrap seeds inputs automatically; if it failed, run `scripts/nix-seed-flake-inputs.sh` manually |
|
|
| Bare system cargo | Fails: `edition2024`, missing wasm target | **Always use `nix develop`** — this is the required toolchain |
|
|
| `bd dolt push` | Fails: 403 outbound | Nothing; bead status changes stay local. Say so rather than implying the tracker was updated |
|
|
| `git+ssh://` Dolt remote in `config.yaml` | No ssh client in the container | `git+https://<origin>`, which the hook passes explicitly |
|
|
| `git push`, GitHub API | **Work normally** | — |
|
|
|
|
Nix itself installs and runs fine (no init system, so the daemon needs
|
|
starting by hand). Reads of public GitHub repos over the git protocol work —
|
|
it is specifically the `/archive/*.tar.gz` and `codeload` endpoints that are
|
|
refused.
|
|
|
|
### How nix develop works after bootstrap
|
|
|
|
The bootstrap runs `scripts/nix-seed-flake-inputs.sh` automatically, which seeds
|
|
the flake inputs over git **without touching `flake.nix` or `flake.lock`**.
|
|
After bootstrap, `nix develop` should work. If it fails, check `/tmp/nix-seed.log`.
|
|
|
|
Why the seeding is needed:
|
|
|
|
- Nix's `github:` fetcher wants a tarball. GitHub traffic **bypasses the
|
|
environment's domain allowlist entirely** and goes through a proxy that
|
|
scopes API and release-asset requests to repositories *attached to the
|
|
session*. A flake input from any other owner gets a 403. Raising network
|
|
access to **Full**, or allowlisting `codeload.github.com`, therefore does
|
|
nothing.
|
|
- Attaching the dependency repos is refused: `cross-tier adds are not
|
|
supported in v1` once the session already has sources from another owner.
|
|
- Nix has no setting that makes `github:` inputs use the git transport.
|
|
|
|
What does work is the lock's own integrity machinery. `flake.lock` records a
|
|
`narHash` per input, and Nix looks a source up in the store and its
|
|
substituters *before* fetching. The git and tarball fetchers produce
|
|
byte-identical trees for a revision, so a `git+https` prefetch at the locked
|
|
rev lands the input at exactly the store path the lock names:
|
|
|
|
```
|
|
lock narHash: sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=
|
|
git prefetch: sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=
|
|
```
|
|
|
|
The script does that for every locked input. Nix still verifies each tree
|
|
against the recorded hash, so this **satisfies** the lock rather than working
|
|
around it — a mismatch fails loudly. Do not instead rewrite the lock's nodes
|
|
to `git` type: carrying the old `narHash` onto a different fetcher is exactly
|
|
the claim the lock exists to make.
|
|
|
|
The bootstrap runs this automatically. It takes a few minutes and several GB of
|
|
store once the devShell builds. If bootstrap reported a seed failure, check
|
|
`/tmp/nix-seed.log` and re-run `scripts/nix-seed-flake-inputs.sh` manually.
|
|
|
|
Two alternatives if per-container seeding is unattractive: push the inputs to
|
|
a binary cache with `nix flake archive` and point sessions at it with
|
|
`NIX_CONFIG`/`extra-substituters` plus a **Custom** allowlist entry for the
|
|
cache host (not GitHub, so the allowlist does apply); or use a self-hosted
|
|
environment, where egress leaves through your own network boundary.
|
|
|
|
`cache.nixos.org` is reachable, so the build itself substitutes normally.
|
|
|
|
---
|
|
|
|
## Sharp edges in `bd`
|
|
|
|
- **`bd dolt push <remote>` ignores its argument** and pushes to `origin`.
|
|
Pointing it at a throwaway remote does not keep the real one out of it;
|
|
only the 403 does. Treat the named form as unsafe.
|
|
- `bd dolt pull` into a divergent local database fails with `local changes
|
|
would be stomped by merge`. Re-sync from the remote instead of merging.
|
|
- `bd` warns if `.beads` is not mode 0700.
|
|
|
|
---
|
|
|
|
## Working conventions
|
|
|
|
- One bead per pull request. Stacking a second bead onto an open PR has
|
|
been rejected in review.
|
|
- A merged PR cannot carry follow-up work: restart from the latest default
|
|
branch and open a new PR.
|
|
- Reconcile diverging history only by merge, including when bringing the
|
|
default branch into a working branch. Never rebase onto main, and never do
|
|
anything that needs a force push. Add a new Conventional Commit by default.
|
|
Only an unpushed HEAD may be amended, and only for a small fix. Never
|
|
reorder or fold commits (`.agents/skills/wave/agent-rules.md`, rule 8).
|
|
- Keep `context/repo-map.md` and `context/design-principles.md` current —
|
|
they are the two docs agents are expected to maintain by hand.
|
|
|
|
---
|
|
|
|
## PR Tracking
|
|
|
|
For any PR you own, **track both CI checks and GitHub comments/reviews**:
|
|
|
|
- **`scripts/pr-watch <n>`**: Waits for checks, then prints all reviews/comments (default).
|
|
Reviews are a separate API surface — Codex/ChatGPT reviews arrive as *reviews* not comments.
|
|
- **Answer feedback with attribution** before marking work done (see below).
|
|
- **Re-check after push** that reviews target the current head SHA.
|
|
|
|
The `pr-watch` skill (`.agents/skills/pr-watch/SKILL.md`) is the agent-facing recipe.
|
|
See AGENTS.md "PR Tracking: Checks AND Reviews" and "Shipping a wave" for the full workflow.
|
|
|
|
---
|
|
|
|
## GitHub Attribution (Hard Rule)
|
|
|
|
**Every GitHub write (PR, comment, review reply) must include an attribution line.**
|
|
Posts go out under the repository owner's account — an unattributed post reads as the
|
|
human's words.
|
|
|
|
Open the body with: `_Posted by <Agent Stack> (<model>)_`
|
|
|
|
Examples:
|
|
- `_Posted by Claude (Opus 4.5)_`
|
|
- `_Posted by Cursor Agent (claude-sonnet-5)_`
|
|
|
|
A thread is not "answered" until the reply carries this attribution. See AGENTS.md
|
|
"GitHub Attribution" for the full rule.
|
|
|
|
---
|
|
|
|
## Knowledge Base
|
|
|
|
**Use `scripts/kb`, not Prolog MCP.** The Prolog MCP is not available in all agent stacks
|
|
(Cursor cloud agents do not have it). All agents must use `scripts/kb` for KB operations:
|
|
|
|
```bash
|
|
scripts/kb check # kb_consistent, exactly what CI runs
|
|
scripts/kb query '<goal>' # run a goal; exit 1 if it fails
|
|
scripts/kb add <delta.pl> # add clauses; refuses if a key already exists
|
|
scripts/kb replace <delta.pl> # add, overwriting existing keys
|
|
scripts/kb rm <keys.pl> # remove by key; refuses if a key is absent
|
|
```
|
|
|
|
Reading `prolog-sessions/kb.pl` directly for queries is fine. See the `kb` skill at
|
|
`.agents/skills/kb/SKILL.md` for the full interface.
|