Revise the deployment model: an agent host and tool VMs #90

Merged
dev-agent merged 12 commits from deployment-model into main 2026-10-02 19:36:33 +00:00
Collaborator

The deployment model we discussed, for review. Only docs/Architecture.md changes. The Development Plan follows in its own PR once this is agreed.

The model

  • The agent host (X1) is one stable VM. Each agent is a container on it, with its own volume, secrets and network, and its MCP servers beside it. It never runs a command a model chose.
  • Tool VMs are disposable, built from a template and reached only over SSH:
    • a build VM per project for nisse-dev, collected when idle and re-created from the template plus the recorded toolchains (D3);
    • its own tool VM for nisse-ops, for network tools (O6);
    • none for a purely conversational agent.
  • Tools and execution (new L13): three kinds.
    • Control tools run in the harness.
    • Execution tools run only through execute(host, …) over SSH, and the harness binds the host. There is no local execution path.
    • MCP tools are the one explicit exception.
    • Tests run against an sshd container.
  • Secrets (L12): a set per agent, on the agent host.
    • The harness hands them out per operation, never on a command line, and never chosen by the model.
    • Every value handed out is redacted from tool output.
    • nisse-dev namespaces its set by project (D7). Each secret's configuration says whether the model's commands may see it.
  • Git (D4): the harness pushes from the build VM, with the key passed over stdin to a short-lived ssh-agent. PRs are opened from the container. Nothing is synced through the agent host.
  • Egress (X2) is split.
    • Agent containers: their Docker network plus the host's firewall.
    • Tool VMs: the VM itself, Docker on it, and UniFi on their VLAN.
    • A project may declare extra egress its tests need, e.g. the nisse project needs LiteLLM and a Matrix test server.
  • Agent-to-agent requests (L1) arrive through the receiving agent's normal intake and carry no authority of their own. The first use: nisse-dev asks nisse-ops for build VMs, via Terraform. You provision them until then.

Points I added that we didn't discuss explicitly

  • A build VM's egress covers Gitea's git endpoint and package sources only. It explicitly can't reach the agent host.
  • "Build artifacts and caches never survive into a new task" now applies to the workspace only. Package caches on a project's build VM stay warm between work items.
  • New open questions:
    • where the per-agent secret sets come from (by hand, synced from Vaultwarden, or written by Terraform);
    • how nisse-ops' MCP servers reach the second site from a shared host (Tailscale on the host serves every container on it);
    • how long a build VM must be idle before it's collected, and whether collecting it needs your word.
  • Removed from Q: "Infrastructure as code for agent VMs". It's now decided (X4).

Effects elsewhere

  • #30 (agent instance per project) is superseded: one nisse-dev with a build VM per project.
  • #89 (token in .git/config) shrinks: the build VM never gets the API token. It's still worth fixing for local bring-up.

I'll close #30 as superseded when this merges.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE

The deployment model we discussed, for review. Only `docs/Architecture.md` changes. The Development Plan follows in its own PR once this is agreed. ## The model - **The agent host** (X1) is one stable VM. Each agent is a container on it, with its own volume, secrets and network, and its MCP servers beside it. **It never runs a command a model chose.** - **Tool VMs** are disposable, built from a template and reached only over SSH: - a **build VM per project** for `nisse-dev`, collected when idle and re-created from the template plus the recorded toolchains (D3); - **its own tool VM** for `nisse-ops`, for network tools (O6); - **none** for a purely conversational agent. - **Tools and execution** (new L13): three kinds. - **Control tools** run in the harness. - **Execution tools** run only through `execute(host, …)` over SSH, and the harness binds the host. There is no local execution path. - **MCP tools** are the one explicit exception. - Tests run against an `sshd` container. - **Secrets** (L12): a set per agent, on the agent host. - The harness hands them out per operation, never on a command line, and never chosen by the model. - Every value handed out is redacted from tool output. - `nisse-dev` namespaces its set by project (D7). Each secret's configuration says whether the model's commands may see it. - **Git** (D4): the harness pushes from the build VM, with the key passed over stdin to a short-lived `ssh-agent`. PRs are opened from the container. Nothing is synced through the agent host. - **Egress** (X2) is split. - **Agent containers:** their Docker network plus the host's firewall. - **Tool VMs:** the VM itself, Docker on it, and UniFi on their VLAN. - A project may declare extra egress its tests need, e.g. the `nisse` project needs LiteLLM and a Matrix test server. - **Agent-to-agent requests** (L1) arrive through the receiving agent's normal intake and carry no authority of their own. The first use: `nisse-dev` asks `nisse-ops` for build VMs, via Terraform. You provision them until then. ## Points I added that we didn't discuss explicitly - **A build VM's egress** covers Gitea's git endpoint and package sources only. It explicitly can't reach the agent host. - **"Build artifacts and caches never survive into a new task"** now applies to the workspace only. Package caches on a project's build VM stay warm between work items. - **New open questions:** - where the per-agent secret sets come from (by hand, synced from Vaultwarden, or written by Terraform); - how `nisse-ops`' MCP servers reach the second site from a shared host (Tailscale on the host serves every container on it); - how long a build VM must be idle before it's collected, and whether collecting it needs your word. - **Removed from Q:** "Infrastructure as code for agent VMs". It's now decided (X4). ## Effects elsewhere - **#30 (agent instance per project) is superseded:** one `nisse-dev` with a build VM per project. - **#89 (token in `.git/config`) shrinks:** the build VM never gets the API token. It's still worth fixing for local bring-up. I'll close #30 as superseded when this merges. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent added 1 commit 2026-10-02 16:35:56 +00:00
Revise the deployment model: an agent host and tool VMs
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m20s
230b927ebe
Agents run as containers on one stable agent host that keeps their
state and secrets and never runs a command a model chose. Model-chosen
commands run on disposable tool VMs over SSH: a build VM per project
for nisse-dev, its own tool VM for nisse-ops. Secrets are a set per
agent, handed out per operation by the harness and redacted from tool
output. MCP servers stay on the agent host as the one exception.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
Author
Collaborator

Added in the second commit: L10 is now a knowledge vault, replacing Outline.

  • One vault of Obsidian-format Markdown on the agent host. Agent memory lives under memory/, one folder per agent. Other folder names are left open on purpose.
  • One writer per folder, enforced by mounts: no agent can read another's memory, and nisse-dev gets no infrastructure material.
  • Links point from memory to shared notes only. Writes are atomic.
  • Access is through control tools (L13), so tool VMs never see the vault.
  • History: a git repo on the host, with each write committed with its agent and work item.
  • Your copy: Syncthing. Agent folders (memory included) are send-only from the host, and the folders you write are receive-only on it, so conflicts can't happen. Memory is visible to you read-only. Corrections still go through conversation.
  • Other edits: L6's memory "where", X5 (Outline out, Syncthing in), and the Appendix.

🤖 Generated with Claude Code

Added in the second commit: **L10 is now a knowledge vault, replacing Outline.** - **One vault of Obsidian-format Markdown** on the agent host. Agent memory lives under `memory/`, one folder per agent. Other folder names are left open on purpose. - **One writer per folder, enforced by mounts:** no agent can read another's memory, and `nisse-dev` gets no infrastructure material. - **Links point from memory to shared notes only.** Writes are atomic. - **Access is through control tools (L13),** so tool VMs never see the vault. - **History:** a git repo on the host, with each write committed with its agent and work item. - **Your copy:** Syncthing. Agent folders (memory included) are send-only from the host, and the folders you write are receive-only on it, so conflicts can't happen. Memory is visible to you read-only. Corrections still go through conversation. - **Other edits:** L6's memory "where", X5 (Outline out, Syncthing in), and the Appendix. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dev-agent added 1 commit 2026-10-02 17:30:54 +00:00
Replace Outline with an Obsidian-format knowledge vault on the agent host
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m21s
aa97309a0c
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent force-pushed deployment-model from 70f8118036 to 0ee251485b 2026-10-02 17:37:42 +00:00 Compare
dev-agent added 1 commit 2026-10-02 17:37:46 +00:00
Make the vault's git history optional
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m20s
3e7edce6dc
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent force-pushed deployment-model from 0ee251485b to 3e7edce6dc 2026-10-02 17:37:46 +00:00 Compare
Author
Collaborator

Third commit: the dev workflow we walked through.

  • Intake (D1, L1):
    • an issue assigned to dev-agent is a work item, and your issue is its record;
    • unassigned issues are backlog;
    • Gitea issue dependencies mark an item blocked, and it becomes ready only when they close;
    • work item states are active, ready, waiting on you, and blocked;
    • the order is yours when you give one, otherwise oldest first.
  • Starting an item (D1): the agent restates its understanding in the item's Matrix thread.
    • Issues labelled bug proceed after a grace period.
    • Everything else waits for your go-ahead.
    • It talks first when the issue is labelled discuss, the report is unclear, or it can't reproduce the bug.
    • It never classifies an issue itself.
  • Documents (D2):
    • ARCHITECTURE.md is kept current and reviewed in PRs;
    • design asks for the design to be agreed before code;
    • build plans are the agent's working documents in the repo, not gates, and the first PR of a multi-milestone piece of work carries the whole plan;
    • progress is recorded in the plan, and the framework never parses it.
  • Scope (L3, P3, D6): the assigned issue plus what was agreed in its conversation. Milestone markings and plan approval are gone as framework concepts. The trust dial is per project.
  • Conversation (L5):
    • free-form talk can open a work item;
    • each work item gets a Matrix thread, and replies route to it;
    • documents arrive as pasted text, attachments, or a pointer to a vault note.
  • Git (D4):
    • start_milestone and finish_milestone are control tools, guarded so the model's mistakes are harmless;
    • the workspace is never on the default branch;
    • the next milestone waits for the previous merge;
    • parking pushes the item's branch;
    • the agent never owns or administers a repo, which settles #29's ownership question.
  • Q: stacked PRs, for later.

🤖 Generated with Claude Code

Third commit: **the dev workflow we walked through.** - **Intake (D1, L1):** - an issue assigned to `dev-agent` is a work item, and your issue is its record; - unassigned issues are backlog; - Gitea issue dependencies mark an item blocked, and it becomes ready only when they close; - work item states are active, ready, waiting on you, and blocked; - the order is yours when you give one, otherwise oldest first. - **Starting an item (D1):** the agent restates its understanding in the item's Matrix thread. - Issues labelled `bug` proceed after a grace period. - Everything else waits for your go-ahead. - It talks first when the issue is labelled `discuss`, the report is unclear, or it can't reproduce the bug. - It never classifies an issue itself. - **Documents (D2):** - `ARCHITECTURE.md` is kept current and reviewed in PRs; - `design` asks for the design to be agreed before code; - build plans are the agent's working documents in the repo, not gates, and the first PR of a multi-milestone piece of work carries the whole plan; - progress is recorded in the plan, and the framework never parses it. - **Scope (L3, P3, D6):** the assigned issue plus what was agreed in its conversation. Milestone markings and plan approval are gone as framework concepts. The trust dial is per project. - **Conversation (L5):** - free-form talk can open a work item; - each work item gets a Matrix thread, and replies route to it; - documents arrive as pasted text, attachments, or a pointer to a vault note. - **Git (D4):** - `start_milestone` and `finish_milestone` are control tools, guarded so the model's mistakes are harmless; - the workspace is never on the default branch; - the next milestone waits for the previous merge; - parking pushes the item's branch; - the agent never owns or administers a repo, which settles #29's ownership question. - **Q:** stacked PRs, for later. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dev-agent added 1 commit 2026-10-02 18:26:03 +00:00
Write the agreed dev workflow into the architecture
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m19s
cd2ff6d769
Issues assigned to dev-agent are the intake; the agent restates its
understanding and either proceeds (bug label) or waits for a go-ahead.
Labels steer and are never required. Build plans and ARCHITECTURE.md
are working documents reviewed in PRs, not gates; scope is the issue
and its conversation. Work items can be blocked on Gitea dependencies,
each gets a Matrix thread, milestones are started and finished by
control tools, and the next milestone waits for the previous merge.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent added 1 commit 2026-10-02 18:26:59 +00:00
Let the agent file issues from conversation (later addition)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m17s
acf7ce191c
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent added 1 commit 2026-10-02 18:30:33 +00:00
Fix inconsistencies and gaps found re-reading the architecture
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m27s
349ec794f2
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent added 1 commit 2026-10-02 18:35:00 +00:00
Accept a plain-language go-ahead, announced and revision-bound
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m16s
d77c142488
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
Author
Collaborator

Latest commit: condensed the architecture from about 12,000 to 7,700 words. The rule was: no decision added or removed, only merged, moved or cut.

  • Each rule is stated once, in its home section; other sections refer to it by ID. For example, the build VM lifecycle is now only in D3, secret handout only in L12, and the MCP exception only in L13.
  • D1's labels are now a table.
  • Mechanism detail moved to docs/Development-Plan.md §6, "Implementation notes", keyed by architecture section:
    • the 10-minute grace default;
    • the revision-stamping rules per channel;
    • the context-fitting order and view labels;
    • render-time details;
    • SQLite WAL and fsync;
    • tool-choice enforcement;
    • write-then-rename;
    • environment or stdin for secrets;
    • the Authelia single-factor exception;
    • preflight manifests;
    • excludes and the push ssh-agent;
    • the port range;
    • ZFS and bpg/proxmox;
    • llama-swap.
  • Removed:
    • P8 was folded into P1 (self-hosting, nothing load-bearing held remotely), P5 and X1;
    • the Appendix about the old Build Specification is in git history.
  • Section IDs are unchanged. The code and the Development Plan refer to them.

I checked the rewrite against the previous version, decision by decision. Five dropped ones were restored:

  • installing on others' hosts is class 3;
  • snapshots before risky changes;
  • ops resume needs an unexpired approval;
  • the classifier runs on the agent host;
  • the build VM's browser has no SSO.

🤖 Generated with Claude Code

Latest commit: **condensed the architecture** from about 12,000 to 7,700 words. The rule was: no decision added or removed, only merged, moved or cut. - **Each rule is stated once, in its home section;** other sections refer to it by ID. For example, the build VM lifecycle is now only in D3, secret handout only in L12, and the MCP exception only in L13. - **D1's labels are now a table.** - **Mechanism detail moved to `docs/Development-Plan.md` §6, "Implementation notes",** keyed by architecture section: - the 10-minute grace default; - the revision-stamping rules per channel; - the context-fitting order and view labels; - render-time details; - SQLite WAL and fsync; - tool-choice enforcement; - write-then-rename; - environment or stdin for secrets; - the Authelia single-factor exception; - preflight manifests; - excludes and the push `ssh-agent`; - the port range; - ZFS and `bpg/proxmox`; - llama-swap. - **Removed:** - **P8** was folded into P1 (self-hosting, nothing load-bearing held remotely), P5 and X1; - **the Appendix** about the old Build Specification is in git history. - **Section IDs are unchanged.** The code and the Development Plan refer to them. I checked the rewrite against the previous version, decision by decision. Five dropped ones were restored: - installing on others' hosts is class 3; - snapshots before risky changes; - ops resume needs an unexpired approval; - the classifier runs on the agent host; - the build VM's browser has no SSO. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dev-agent added 1 commit 2026-10-02 18:43:17 +00:00
Condense the architecture; move mechanism detail to the Development Plan
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m18s
6e4dca040c
Each rule is stated once in its home section and referred to by ID
elsewhere. No decision added or removed; implementation detail moved to
Development-Plan.md section 6, keyed by architecture section. P8 folded
into P1, P5 and X1; the Appendix about the old spec dropped. Section
IDs are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent added 1 commit 2026-10-02 18:52:19 +00:00
Drop Vikunja: Gitea issues are the one tracker for every agent
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m17s
4ca8e1f550
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
dev-agent added 1 commit 2026-10-02 18:53:45 +00:00
Define projects as configuration entries (D8); note the agent host's recovery
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m19s
5839091d65
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent force-pushed deployment-model from 775dabcc18 to 5839091d65 2026-10-02 18:53:45 +00:00 Compare
Owner

In P3, you number the classifications and then later talk about things like a "class 3" action. Perhaps it would be better to stick to get rid of the numbers and just use the labels.

In P3, you number the classifications and then later talk about things like a "class 3" action. Perhaps it would be better to stick to get rid of the numbers and just use the labels.
Owner

"Escalation never depends on self-assessment alone." If the local model can call for help, isn't that self-assessment?

"Escalation never depends on self-assessment alone." If the local model can call for help, isn't that self-assessment?
Owner

With the new VM, maybe we'll want a different DB style. For example, maybe PostgreSQL would make sense. We should probably stick with the current plan for MVP, but I can see it changing later if we have scaling or backup issues or something.

With the new VM, maybe we'll want a different DB style. For example, maybe PostgreSQL would make sense. We should probably stick with the current plan for MVP, but I can see it changing later if we have scaling or backup issues or something.
dev-agent added 1 commit 2026-10-02 19:24:55 +00:00
Close five gaps the loop model found
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m18s
8c38444b88
- abandon closes the item's open PRs
- a PR the operator closed is an answer, never reopened by a retry
- a review fix for a PR that merged meanwhile goes out as a new PR
- redoing a milestone after a closed PR gets a new branch and PR
- a record issue carries its work item's ID from creation

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
Owner

"Secrets, identity and logging"

Not for MVP, but we may eventually want nisse-ops to hand out secrets in some cases. For example, SSH keys to a new VM, or gitea credentials to a new project.

I'm not at all sure how to handle that, and it's certainly future work.

"Secrets, identity and logging" Not for MVP, but we may eventually want nisse-ops to hand out secrets in some cases. For example, SSH keys to a new VM, or gitea credentials to a new project. I'm not at all sure how to handle that, and it's certainly future work.
Owner

We mentioned using Matrix threads, but a little more clarity about when they will be started would probably be good.

Also, could they help the framework disambiguate where a command should apply?

We mentioned using Matrix threads, but a little more clarity about when they will be started would probably be good. Also, could they help the framework disambiguate where a command should apply?
Owner

Not for MVP, but we should talk about project releases at some point. I tend to setup my projects to build and publish artifacts at every release. Most of the time I do releases via tags, but could possibly need to use release branches at some point.

Not for MVP, but we should talk about project releases at some point. I tend to setup my projects to build and publish artifacts at every release. Most of the time I do releases via tags, but could possibly need to use release branches at some point.
Author
Collaborator

Thanks. All six are addressed in 2187c24:

  • Class numbers: dropped. The classes are now harmless / contained / dangerous everywhere: P3, P4, L3, D3, the D6 and O3 tables, and O1.
  • "Self-assessment alone": fair catch; asking for help is self-assessment. Reworded (P7): escalation doesn't wait for the model to notice. The driver may ask, which is its own judgement, and observable triggers escalate as well, even when it doesn't.
  • PostgreSQL: agreed. SQLite stays for MVP, and there's a new Q entry: a server database on the agent host if scaling or backups call for it, still one database and role per agent.
  • Ops handing out secrets: added to Q. Writing into another agent's secret set crosses L12's isolation, so it needs its own channel and approval rule, to design when we get there.
  • Threads (L5):
    • When one starts: with the item. For an assigned issue, the agent's acknowledgement is the thread root. For a conversation, your own top-level message is.
    • Mapping: the item records its thread, so the link survives restarts.
    • Disambiguation, yes: inside a thread, every command applies to that item. At top level, status is the agent's and stop is the active item's. A command naming an item ("abandon #14") applies to that item. Any other command is ambiguous, and the agent asks rather than guessing.
  • Releases: added to Q: tag- or release-branch-driven artifact publishing, what the agent may do (dangerous unless the trust dial allows), and how a build plan names a release.

🤖 Generated with Claude Code

Thanks. All six are addressed in `2187c24`: - **Class numbers:** dropped. The classes are now **harmless / contained / dangerous** everywhere: P3, P4, L3, D3, the D6 and O3 tables, and O1. - **"Self-assessment alone":** fair catch; asking for help *is* self-assessment. Reworded (P7): *escalation doesn't wait for the model to notice*. The driver may ask, which is its own judgement, and observable triggers escalate as well, even when it doesn't. - **PostgreSQL:** agreed. SQLite stays for MVP, and there's a new Q entry: a server database on the agent host if scaling or backups call for it, still one database and role per agent. - **Ops handing out secrets:** added to Q. Writing into another agent's secret set crosses L12's isolation, so it needs its own channel and approval rule, to design when we get there. - **Threads (L5):** - **When one starts:** with the item. For an assigned issue, the agent's acknowledgement is the thread root. For a conversation, your own top-level message is. - **Mapping:** the item records its thread, so the link survives restarts. - **Disambiguation, yes:** inside a thread, every command applies to that item. At top level, `status` is the agent's and `stop` is the active item's. A command naming an item ("abandon #14") applies to that item. Any other command is ambiguous, and the agent asks rather than guessing. - **Releases:** added to Q: tag- or release-branch-driven artifact publishing, what the agent may do (dangerous unless the trust dial allows), and how a build plan names a release. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dev-agent added 1 commit 2026-10-02 19:33:18 +00:00
Address review comments on the architecture
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m22s
2187c24d0d
Name the action classes harmless, contained and dangerous instead of
numbering them; say what escalation doesn't depend on; say when a work
item's Matrix thread starts and how threads route commands; add open
questions for the state store's engine, ops issuing credentials, and
releases.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dongar approved these changes 2026-10-02 19:35:19 +00:00
dev-agent merged commit d407db72c2 into main 2026-10-02 19:36:33 +00:00
dev-agent deleted branch deployment-model 2026-10-02 19:36:33 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dev/nisse#90