Files
improvise/context/cloud-agents.md
T
Cursor Agent b0c4105be3 docs: add GitHub attribution as a hard rule for all agent stacks
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>
2026-09-25 19:37:48 +00:00

9.1 KiB

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:

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:

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:

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.