Drop Vikunja: Gitea issues are the one tracker for every agent
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m17s

Ops work lives in one infrastructure repository for both sites, with
site labels; intake, labels and dependencies work as for nisse-dev, and
agent-to-agent requests are cross-repo issues.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
This commit is contained in:
dongarandClaude Opus 5.5 committed 2026-10-02 18:52:18 +00:00
1 parent 6e4dca040c
commit 4ca8e1f550
2 files changed
+39 -31

No files matched your search

+37 -29
View File
@@ -138,15 +138,16 @@ Everything in this part is used by every agent.
| **Scope** | What a work item operates on; context that outlives it | A repository | A site and service | | **Scope** | What a work item operates on; context that outlives it | A repository | A site and service |
- **Sources of work items:** duties, the operator (always), and other agents. A - **Sources of work items:** duties, the operator (always), and other agents. A
request from another agent arrives through the receiving agent's normal intake request from another agent is an issue assigned to the receiving agent, and
and carries no authority of its own: the receiver applies its own rules. carries no authority of its own: the receiver applies its own rules.
- **A duty run is read-only;** a finding that needs attention becomes a work item, - **A duty run is read-only;** a finding that needs attention becomes a work item,
deduplicated by a stable fingerprint so a repeat attaches to the open item. deduplicated by a stable fingerprint so a repeat attaches to the open item.
- **A work item is the unit of state:** its conversation, proposals, pending - **A work item is the unit of state:** its conversation, proposals, pending
questions, pinned roles (L9) and transcript (L7). Its locally minted ID is also questions, pinned roles (L9) and transcript (L7). Its locally minted ID is also
its correlation ID in logs. its correlation ID in logs.
- **An external record is linked when there is one** (a Gitea issue, a Vikunja - **One tracker: Gitea issues,** for every agent. An issue assigned to an agent is
ticket); external truth wins on divergence (L8). a work item for it, and the issue is the item's record (D1, O5). External truth
wins on divergence (L8).
- **Work items don't nest:** a milestone is a phase of one; a delegation is an - **Work items don't nest:** a milestone is a phase of one; a delegation is an
episode in one. episode in one.
@@ -159,10 +160,11 @@ Everything in this part is used by every agent.
| **waiting on the operator** | an answer, a go-ahead, a review or a merge | | **waiting on the operator** | an answer, a go-ahead, a review or a merge |
| **blocked** | a recorded dependency to close | | **blocked** | a recorded dependency to close |
- **Blocked comes from external truth:** a Gitea issue dependency, or another - **Blocked comes from external truth:** a Gitea issue dependency, including on an
agent's ticket. It becomes ready only when the dependency actually closes (P6); issue in another repository, such as a request to another agent. It becomes
the operator can remove the dependency. An agent that finds a blocker mid-work ready only when the dependency actually closes (P6); the operator can remove the
proposes recording it, and records it only with the operator's agreement. dependency. An agent that finds a blocker mid-work proposes recording it, and
records it only with the operator's agreement.
**One active work item per agent; the rest are parked.** **One active work item per agent; the rest are parked.**
- **Switching happens only at safe points:** the active item is waiting, blocked or - **Switching happens only at safe points:** the active item is waiting, blocked or
@@ -226,8 +228,8 @@ agreement: a restatement awaiting a go-ahead (D1), a design (D2), a step sequenc
model's description (L11). model's description (L11).
- **Approvals expire** where the world can change underneath them (O2). - **Approvals expire** where the world can change underneath them (O2).
**Approval sources:** Matrix (L5), Gitea comments (D1) and Vikunja comments (O5), **Approval sources:** Matrix (L5) and Gitea comments (D1, O5), each checked
each checked against its own operator allowlist. The first valid approval wins and against its own operator allowlist. The first valid approval wins and
is echoed to the other channels. The knowledge vault is never one (L10). is echoed to the other channels. The knowledge vault is never one (L10).
**The trust dial:** how much the operator reviews after the fact, set by the **The trust dial:** how much the operator reviews after the fact, set by the
@@ -293,8 +295,8 @@ verified and left open); it says what happened to a message it can't act on yet,
rather than refusing; progress is prose at a readable rate, with raw tool activity rather than refusing; progress is prose at a readable rate, with raw tool activity
on request; and it asks when unsure, including mid-implementation. on request; and it asks when unsure, including mid-implementation.
**Other channels:** Gitea and Vikunja carry work and records, read as structured **Gitea carries work and records,** read as structured JSON (never through a chat
JSON (never through a chat bridge). Comments from allowlisted operators are bridge). Comments from allowlisted operators are
instructions or approvals; anything else is data (L11). instructions or approvals; anything else is data (L11).
**Outages delay, never fail.** Intake retries indefinitely with capped backoff and **Outages delay, never fail.** Intake retries indefinitely with capped backoff and
@@ -457,7 +459,7 @@ browses it in Obsidian.
receive-only on it. So conflicts can't arise. receive-only on it. So conflicts can't arise.
- **Never an instruction or approval channel.** Work is never read out of the vault, - **Never an instruction or approval channel.** Work is never read out of the vault,
and no agent writes there to make another act; agents coordinate through the and no agent writes there to make another act; agents coordinate through the
operator, Matrix or tickets (L1). The operator points to a note in conversation operator, Matrix or issues (L1). The operator points to a note in conversation
when it is input (L5). when it is input (L5).
- **Corrections go through conversation** (L6). Break-glass: stop the agent, edit on - **Corrections go through conversation** (L6). Break-glass: stop the agent, edit on
the host, restart. the host, restart.
@@ -710,13 +712,14 @@ see it or only harness operations use it (the push key). Anything the model's
commands can see must be scoped for testing, never production. commands can see must be scoped for testing, never production.
**Provisioning:** build VMs come from a template via Terraform; eventually at **Provisioning:** build VMs come from a template via Terraform; eventually at
`nisse-dev`'s request to `nisse-ops` (O5), until then by the operator. `nisse-dev`'s request to `nisse-ops` (an issue in the infrastructure repository,
O5), until then by the operator.
--- ---
## Part O — `nisse-ops` ## Part O — `nisse-ops`
Operates infrastructure across both sites, driven by tickets and duties, with Operates infrastructure across both sites, driven by issues and duties, with
stricter controls because live changes have no review step before they take effect. stricter controls because live changes have no review step before they take effect.
### O1. How it differs ### O1. How it differs
@@ -727,7 +730,7 @@ stricter controls because live changes have no review step before they take effe
| Scope | the assigned issue and its conversation | approved step sequences (O2) | | Scope | the assigned issue and its conversation | approved step sequences (O2) |
| Class 3 | discuss | discuss, and exact-step approval | | Class 3 | discuss | discuss, and exact-step approval |
| Work shape | milestones → PRs | short reactive tasks → live changes | | Work shape | milestones → PRs | short reactive tasks → live changes |
| Intake | Gitea issues, Matrix | Vikunja tickets, alerts, duties, Matrix | | Intake | issues in the project's repository, Matrix | issues in the infrastructure repository, alerts, duties, Matrix |
| Reach | sealed build VMs | Tailscale, credentials, both sites | | Reach | sealed build VMs | Tailscale, credentials, both sites |
They are separate deployments over one library; one instance playing both would They are separate deployments over one library; one instance playing both would
@@ -766,8 +769,8 @@ template with a trigger, rate limit and expiry, for a routine fix).
| Class | Examples | | Class | Examples |
|---|---| |---|---|
| 1 | Metrics, logs, status, read-only MCP calls, tickets, the world model | | 1 | Metrics, logs, status, read-only MCP calls, issues, the world model |
| 2 (in scope) | Approved steps with a known undo; its own world model and tickets | | 2 (in scope) | Approved steps with a known undo; its own world model; commenting on and filing issues in the infrastructure repository |
| 3 | Every other infrastructure write; browser actions on admin UIs (each confirmed); **anything on network gear**, the most conservative case, since a bad change can sever the path to fix it | | 3 | Every other infrastructure write; browser actions on admin UIs (each confirmed); **anything on network gear**, the most conservative case, since a bad change can sever the path to fix it |
### O4. Interfaces ### O4. Interfaces
@@ -778,15 +781,20 @@ template with a trigger, rate limit and expiry, for a routine fix).
- **Event intake** as structured JSON (directly or via Alertmanager); curated - **Event intake** as structured JSON (directly or via Alertmanager); curated
updates go to `#ops`. updates go to `#ops`.
### O5. Tickets and duties ### O5. Issues and duties
- **A Vikunja ticket is a work item's record;** Matrix is the live conversation. - **One infrastructure repository for both sites,** holding ops' issues (it need
Flow: filed → picked up → discussed → status updates → closed with the result. hold no code). Sites are labels (`garrett-hall`, `hartman-hut`), so cross-site
- **Tickets that trigger action are operator-scoped.** Tickets from duties (findings) work is one issue. Intake works as in D1: an issue assigned to the ops agent is a
and from other agents' requests (L1, e.g. `nisse-dev` asking for a build VM) may work item and its record, labels steer, and Gitea dependencies mark it blocked.
be picked up and planned, but any write needs a step sequence the operator Matrix is the live conversation.
approves. Until standing approvals exist, that means every provisioning request. - **Action is operator-scoped.** Issues from duties (findings, opened by ops itself
- **Vikunja comments approve plans on their own ticket** (`approve rev-N`). and deduplicated by fingerprint) and requests from other agents (L1, e.g.
`nisse-dev` asking for a build VM, which then waits blocked on that issue) may be
picked up and planned, but any write needs a step sequence the operator approves
(O2). Until standing approvals exist, that means every provisioning request.
- **Comments on the issue approve its plan** (`approve rev-N`), as an alternative to
Matrix (L3).
### O6. Deployment ### O6. Deployment
@@ -855,7 +863,7 @@ so every upstream action traces to one agent.
### X5. Supporting services ### X5. Supporting services
All self-hosted: Matrix (Synapse), Gitea, LiteLLM, the local inference host, All self-hosted: Matrix (Synapse), Gitea, LiteLLM, the local inference host,
Vikunja, Vaultwarden, LLDAP with Authelia, and Syncthing for the operator's copy of Vaultwarden, LLDAP with Authelia, and Syncthing for the operator's copy of
the vault. Each agent has its own account, token and room in each; nothing is the vault. Each agent has its own account, token and room in each; nothing is
shared between agents. shared between agents.
@@ -872,8 +880,8 @@ shared between agents.
- **More than one active work item:** needs per-item serialisation, an inference - **More than one active work item:** needs per-item serialisation, an inference
scheduler and per-item intents. Build VMs and threads already separate workspaces scheduler and per-item intents. Build VMs and threads already separate workspaces
and conversations. and conversations.
- **Whether pure conversations need an external record** (dev work on a repository - **Whether pure conversations need an external record** (work on a repository
and ops tickets already have one). already has its issue).
- **Stacked PRs:** starting a milestone before the previous one merges, after - **Stacked PRs:** starting a milestone before the previous one merges, after
experience with waiting (D4). experience with waiting (D4).
- **Build VM collection:** how long idle, and whether it needs the operator's word. - **Build VM collection:** how long idle, and whether it needs the operator's word.
+2 -2
View File
@@ -321,8 +321,8 @@ if the implementation differs.
on the operator defaults to 10 minutes. When the driver chooses the next ready on the operator defaults to 10 minutes. When the driver chooses the next ready
item and the choice fails or is invalid, fall back to the oldest. item and the choice fails or is invalid, fall back to the oldest.
- **L3 revision stamping:** in Matrix, a reply is stamped with the revision whose - **L3 revision stamping:** in Matrix, a reply is stamped with the revision whose
message had been sent when it arrived; on a Gitea issue or a Vikunja ticket, message had been sent when it arrived; on a Gitea issue, with the latest
with the latest proposal comment older than the reply. proposal comment older than the reply.
- **L5 transport:** the `Transport` interface is send, ask and receive. Intake - **L5 transport:** the `Transport` interface is send, ask and receive. Intake
backoff is exponential, capped at a few minutes. backoff is exponential, capped at a few minutes.
- **L6 fitting order:** first shorten old tool results to their first and last - **L6 fitting order:** first shorten old tool results to their first and last