Files
paperclip-harness/docs/ENVIRONMENT-FACTS.md

6.8 KiB

Facts about this machine, checked 2026-11-09

Everything here was measured with a command. Anything not measured is marked unproven.

Paperclip

  • Running locally: http://127.0.0.1:3100. Public UI: https://paperclip.lab.audasmedia.com.au.
  • Company: d4921013-e5da-4d88-8016-57d5746e2d03
  • Agents, all running the Pi adapter (pi_local), all idle:
    • Hub — 108c6220-c9e1-4b62-9e0a-6a763e0d28fd (this is the identity of PAPERCLIP_API_KEY)
    • Builder — 403de1f7-645c-4d35-bc7e-19b01d77bacc
    • Chief of Staff — 232f1f9e-bac0-4185-8a0e-eddbead33e04
    • Documenter — 706ffc88-120f-46c4-a5d9-ffa12e2ad5f0
    • researcher — a6a2c0ee-570e-4f89-a977-83136b534a2f
    • System — fe7a1881-1df9-481b-af74-87292fef288c
  • Writes need the user key: PAPERCLIP_BOARD_KEY. The agent key PAPERCLIP_API_KEY is refused with 403 outside a heartbeat run.
  • Blockers live at GET /api/issues/{id}/diagnostics/blockers, not on the task list.

The sandbox project

  • spike-2026-11-09 is archived: status cancelled, renamed spike-2026-11-09 (deleted), id 9e3f61f6-cce9-49b1-8083-3130345a04a5.
  • DELETE /api/projects/{id} returned 500, so it was archived instead. Its two tasks (AUD-157, AUD-158) remain inside the archived project. Deleting an archived project is still untested.
  • Its scratch repo /tmp/pc-sandbox was removed.
  • To make a fresh sandbox, use the payload recorded in PAPERCLIP-API-NOTES.md: POST /api/companies/{companyId}/projects with name, status: "backlog" and workspace: { name, sourceType: "git_repo", cwd, isPrimary: true }.

Does a heartbeat wake an agent? PROVEN, 2026-11-10

It does, and the wake is not a timer. Assigning a task woke Builder within one tenth of a second, with no call to heartbeat/invoke.

Measured on spike-2026-11-10 / AUD-159:

00:01:24.891Z  PATCH /api/issues/AUD-159 {"assigneeAgentId":"403de1f7-..."}  -> 200 todo
00:01:24.937Z  wake request recorded: source=assignment reason=issue_assigned
00:01:25.036Z  run aae77e89-... claimed, adapter pi_local, issue -> in_progress
00:01:51.351Z  agent comment posted (commit b093301)
00:01:53.153Z  issue -> done
00:01:59.377Z  run -> succeeded

So the four documented wake sources all reach an agent: a timer tick, an assignment or a new comment on its own task, a person clicking wake, and a routine firing. The timer is opt-in and is off for most agents; Builder currently has heartbeat.enabled: true, so it also polls. Assignment alone is enough.

POST /api/agents/{id}/heartbeat/invoke was never needed and remains untested. The documented manual wake is POST /api/agents/{id}/wakeup with {"source":"on_demand","triggerDetail":"manual","forceFreshSession":...}.

A wake can still be refused without any error reaching us. Read GET /api/issues/{id}/diagnostics/wakes — it shows each wake request, its claimed run, and a plain-English diagnosis. Refusal reasons seen in the documentation: the agent is paused, its budget is exhausted, its cooldown has not elapsed, or its run slot is full.

Isolated workspaces: switched on 2026-11-10, and measured working

The instance first had them off. With the flags off, the project's request for a git worktree per task was silently ignored: AUD-159 worked in /tmp/pc-sandbox-2026-11-10 on main, and the task's executionWorkspaceId read null.

Then, with the person's approval, two experimental settings were switched on:

PATCH /api/instance/settings/experimental
{"enableIsolatedWorkspaces": true, "enableWorktreeRunExecution": true}
→ 200

enableIsolatedWorkspacesByDefault was deliberately left off. That flag would give every project without a policy of its own a worktree, which would change the other nine projects on this instance. Only projects that ask for one now get one.

The next task (AUD-160) made a real worktree, and Paperclip posted a "Workspace Ready" comment on the task naming it:

strategy   git_worktree
branch     AUD-160-milestone-1-t2-read-hello-txt
cwd        /tmp/pc-sandbox-2026-11-10/.paperclip/worktrees/AUD-160-milestone-1-t2-read-hello-txt
baseRef    main
deliveryState  merged_by_ancestry   (no commit was needed; the branch equals main)

git worktree list in the sandbox repository shows that path on that branch. So the worktree is Paperclip's job after all, once the instance allows it, and the terminal program never needs to run git worktree itself.

Fonts, 2026-11-10

Measured, because the answer was "I thought I had installed them":

  • No Nerd Font was installed (fc-list | grep -i nerd returned nothing) and no JetBrains Mono either. Ghostty ships a plain JetBrains Mono of its own, which is why a terminal can look right while every icon renders as a box.
  • Starship is not installed, and there is no ~/.config/starship.toml.
  • TUIOS has four glyph sets — ascii, default, heavy, unicode — and default is active, which is ordinary Unicode, not Nerd Font icons.
  • TUIOS has 30 themes including six Catppuccin variants, and no look is applied: tuios look show says "No look is applied". The session is not on Catppuccin.

What was changed:

  • fonts.packages = [ nerd-fonts.jetbrains-mono ] and fonts.fontconfig.enable = true in /etc/nixos/configuration.nix, so every machine built from this flake gets it: .13, .27, .51. nix build --dry-run evaluates and wants nerd-fonts-jetbrains-mono-3.4.0+2.304. The rebuild is still to be run (sudo needs a password here).
  • ~/.config/ghostty/config sets font-family = "JetBrainsMono Nerd Font".
  • Rebuilt by the person on 2026-11-10: fc-list | grep -ci nerd now returns 96, and JetBrainsMonoNerdFont-Regular.ttf is present in the store. The font is installed on .13; .27 and .51 get it from the same flake on their next rebuild.
  • The theme is now set: theme = 'catppuccin_mocha' in ~/.config/tuios/config.toml. tuios set-config refused for the running session ("would change this machine, not the session"), so the running session keeps its old chrome until it is restarted.

Toolchain

  • Go is installed (2026-11-10), by nix profile install nixpkgs#go → go1.26.5 at /home/sam/.nix-profile/bin/go. That is the quick path: it works now, and it is not part of the system closure.
  • The durable path is also prepared: go and gopls were added to environment.systemPackages in /etc/nixos/configuration.nix. nix flake check passes and the dry-run build evaluates. The rebuild has not been run, because sudo needs a password here. One command finishes it: sudo nixos-rebuild switch --flake /etc/nixos#nixos-desktop. Until then the profile copy is what runs.

The new repository

  • Local git repo only, one commit, no remote. It is not on Gitea. Push it somewhere before relying on it, or accept that only this machine has it.