diff --git a/docs/agent-lifecycle/agent-roster.md b/docs/agent-lifecycle/agent-roster.md
index 51541476..bb0b9683 100644
--- a/docs/agent-lifecycle/agent-roster.md
+++ b/docs/agent-lifecycle/agent-roster.md
@@ -106,16 +106,13 @@ state dirs work as for every other agent.
deploy log). Any agent holding it gets the same mounts.
The operator dashboard's `POST /api/meta-update` is the only path
that writes `flake.lock`.
-- **Prompt** — identical for every container but one block (below):
- `prompts/system.md`
+- **Prompt** — identical for every container: `prompts/system.md`
carries `` / `` marker
blocks, and `prompt::render` filters for `"agent"` unconditionally,
manager included ("always `agent` role — there is only one role",
`hive-agent/src/prompt.rs`'s own module doc). The `role:manager`
blocks are dead in production, exercised only by a unit test
- (`filter_blocks(SAMPLE, "role", "manager")`). The one block that differs
- is `` vs ``: an agent built
- from an [archetype](../swarm/archetypes.md) is told it has no config repo.
+ (`filter_role_blocks(SAMPLE, "manager")`).
- **Tool allow-list** — the MCP tools claude sees come from the agent's
permissions alone, the same mechanism for every agent
([`docs/turn-loop/mcp.md`](../turn-loop/mcp.md)). Ruth's permissions
diff --git a/docs/agent-lifecycle/config-changes.md b/docs/agent-lifecycle/config-changes.md
index 85c971b7..e08cac73 100644
--- a/docs/agent-lifecycle/config-changes.md
+++ b/docs/agent-lifecycle/config-changes.md
@@ -65,8 +65,6 @@ Creating a brand-new agent is swarm-level (`swarmctl agent create`,
an agent. The swarm controller's `InitAgentConfigRepo` job seeds the
agent's config repo with a default `agent.nix` template, then asks the
target hive to deploy it.
-An agent created from an [archetype](../swarm/archetypes.md) gets no
-config repo: its hive builds it from the archetype's module.
Changing what the template seeded isn't a special case: like every
later change, it's a PR on that config repo, made from a clone and
diff --git a/docs/agent-lifecycle/persistence.md b/docs/agent-lifecycle/persistence.md
index ee46d818..26929d39 100644
--- a/docs/agent-lifecycle/persistence.md
+++ b/docs/agent-lifecycle/persistence.md
@@ -420,12 +420,6 @@ reads it at every container start for `manage_root_agent`. Each agent gets
its own entry from it as `swarm-permissions.json` in its runtime dir, which
it holds until its own first read of its key succeeds.
-`/var/lib/hyperhive/swarm-agent-archetypes.json` holds the archetype each of
-this hive's archetype agents runs, as last read from the swarm's
-`agent-archetype` bucket at the agent's provision and each rebuild. An agent
-with an entry has no `applied/` repo and no `agent-` meta input; see
-[archetypes](../swarm/archetypes.md).
-
hive-c0re renders containers onto `meta#` at creation.
## Destroy vs purge
diff --git a/docs/swarm/archetypes.md b/docs/swarm/archetypes.md
index ab49de4e..c9708a6c 100644
--- a/docs/swarm/archetypes.md
+++ b/docs/swarm/archetypes.md
@@ -1,24 +1,21 @@
# Agent archetypes
-An archetype is a named agent setup: settings to create the agent with, and
-a NixOS module its container runs. The swarm UI's create form lists the
-archetypes the swarm knows. Picking one fills the form's permissions,
-resource caps and inference fields from it, and you can still change each
-field before you create the agent.
+An archetype is a named set of settings to create an agent from. The swarm
+UI's create form lists the archetypes the swarm knows. Picking one fills the
+form's permissions, resource caps and inference fields from it, and you can
+still change each field before you create the agent.
-An agent created from an archetype has no `agent-configs/` repo of its
-own. Its hive builds it from the archetype's module, so every agent of that
-archetype runs the same configuration. To change what it runs, change the
-archetype. Picking "none" creates a custom agent, with its own config repo.
+The agent you create this way is an ordinary agent: it gets its own
+`agent-configs/` repo like any other, and the request carries only the
+fields as the form shows them. Nothing records which archetype you picked.
## The built-in archetypes
The hyperhive flake ships these:
-| archetype | what it sets |
-| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `reviewer` | permissions `messaging`, `inbox`, `execution`: the default set without `meta`. With `execution` it can run `hive-forge`, `git` and other commands. |
-| `android-dev` | installs `android-tools` (`adb`, `fastboot`), Gradle and a JDK; default permissions. |
+| archetype | what it sets |
+| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `reviewer` | permissions `messaging`, `inbox`, `execution`: the default set without `meta`. With `execution` it can run `hive-forge`, `git` and other commands. |
## Where an archetype comes from
@@ -41,8 +38,8 @@ hyperhiveArchetypes.reviewer = {
- Every archetype needs a `description`. `permissions`, `limits` and
`inference` are optional and take the shapes `POST /api/agents` takes. The swarm ignores
other keys in `meta`.
-- `module` is a NixOS module for the agent's container. A hive imports it
- into each agent created from the archetype.
+- `module` is a NixOS module for the agent's container. The swarm doesn't
+ apply it yet.
Today the swarm reads one flake: the hyperhive source the
[builder](builder.md)'s host runs, so only the built-ins appear.
@@ -88,46 +85,3 @@ The stored value:
"refused": { "broken": "limits: …" }
}
```
-
-## Creating an agent from an archetype
-
-The create form sends the picked archetype as `archetype` on
-`POST /api/agents`, `{ "source": "hyperhive", "name": "reviewer" }`. The
-controller refuses with 400 an archetype the stored list doesn't hold, then:
-
-1. stores the choice in the `agent-archetype` KV bucket, keyed by agent name,
- next to the agent's permissions, caps and inference;
-2. queues the creation graph without `CreateRepo`, `AddRepoMember` and
- `InitAgentConfigRepo`. Identity, forge user, docs read, the mints and the
- wanted state stay, and the deploy waits on those alone.
-
-Destroying the agent deletes its key.
-Every hive may read any key of the bucket
-(`$JS.API.DIRECT.GET.KV_agent-archetype.>`) and write none; only the
-controller writes it.
-
-Deploy `swarm-nats-auth` before the hives: every provision reads the
-agent's key, and a hive whose queue connection predates the grant gets a
-refused read, so its `Provision` nodes fail until it reconnects.
-
-The hive reads the agent's key when it provisions the agent and on every
-rebuild, and keeps the last value read in
-`/var/lib/hyperhive/swarm-agent-archetypes.json`, so the meta flake renders
-without the queue. When the read fails, a rebuild keeps the value
-stored there. For an archetype agent the hive:
-
-- seeds no `proposed` or `applied` repo, and gives the meta flake no
- `agent-` input. `mkAgent` imports
- `hyperhive.hyperhiveArchetypes..module` in place of the agent's own
- flake, and sets `HIVE_ARCHETYPE` in the harness environment;
-- relocks no agent input on a rebuild or a meta-input bump, and ignores the
- `rev` of a swarm deploy request;
-- mounts an empty `/agents//config/`.
-
-The agent's system prompt says it has no config repo and names its
-archetype.
-
-The hive takes the module from its own `hyperhive` input. When that input
-predates the archetype, the agent's build fails with
-`this hive's hyperhive input has no archetype `. Update the hive's
-`hyperhive` input to fix it.
diff --git a/docs/turn-loop/claude-invocation.md b/docs/turn-loop/claude-invocation.md
index 22b1ba15..c1441c99 100644
--- a/docs/turn-loop/claude-invocation.md
+++ b/docs/turn-loop/claude-invocation.md
@@ -255,12 +255,7 @@ needs to `chown` a bind mount), once at startup:
`hive-agent/prompts/system.md` by `hive-agent`'s `prompt::render`:
HTML-comment markers (`...`,
same for `role:manager`) gate the role-specific blocks; both flavors
- share everything else. `` and
- `` blocks gate the config-repo paragraphs: an
- agent with `HIVE_ARCHETYPE` set (the meta flake sets it on an agent built
- from an [archetype](../swarm/archetypes.md)) gets the archetype block and
- every other agent the repo block, with `{archetype}` filled in with the
- archetype's name. Five placeholders are then
+ share everything else. Five placeholders are then
substituted: `{label}` (short agent name), `{qualified_label}`
(hive-qualified `name@domain` form),
`{hive_identity}` (for example `` on hive `pr1ma` ``; empty when
@@ -280,17 +275,14 @@ needs to `chown` a bind mount), once at startup:
telling the agent where the docs live.
Passed via `--system-prompt-file`.
- **Marker grammar.** `` opens a block; any
- `` closes the current block of that kind. The renderer
- filters the two kinds one after the other. The renderer always uses
- role `agent`, so it elides blocks with other role tags, and config `repo`
- or `archetype` as above. Nesting **isn't**
+ **Marker grammar.** `` opens a block; any
+ `` closes the current block. The renderer always uses
+ role `agent`, so it elides blocks with other role tags. Nesting **isn't**
supported — a stray opener with no closer runs until end of file.
The renderer tolerates whitespace inside markers (`` parses the
same as ``). Content outside any marker is always
- included. Today's `system.md` carries no role markers (single agent
- role), and the role grammar stays wired for a future manager / multi-role
- prompt; it carries one pair of config blocks.
+ included. Today's `system.md` carries no markers (single agent role) —
+ the grammar stays wired for a future manager / multi-role prompt.
**`hive_identity` / `swarm_identity` shape.** Each carries a
leading space + backticked name (` on hive \`pr1ma\``,
diff --git a/frontend/packages/swarm-ui/src/pages/CreateAgentArchetype.ts b/frontend/packages/swarm-ui/src/pages/CreateAgentArchetype.ts
index 508fcf64..6b1edc73 100644
--- a/frontend/packages/swarm-ui/src/pages/CreateAgentArchetype.ts
+++ b/frontend/packages/swarm-ui/src/pages/CreateAgentArchetype.ts
@@ -61,13 +61,3 @@ export function prefill(
},
};
}
-
-/**
- * The `archetype` field of `POST /api/agents` for `archetype`, or nothing for
- * a custom agent.
- */
-export function requestArchetype(
- archetype: Archetype | undefined,
-): { source: string; name: string } | undefined {
- return archetype && { source: archetype.source, name: archetype.name };
-}
diff --git a/frontend/packages/swarm-ui/src/pages/CreateAgentForm.tsx b/frontend/packages/swarm-ui/src/pages/CreateAgentForm.tsx
index 3074c765..e9734be3 100644
--- a/frontend/packages/swarm-ui/src/pages/CreateAgentForm.tsx
+++ b/frontend/packages/swarm-ui/src/pages/CreateAgentForm.tsx
@@ -57,7 +57,6 @@ import {
import {
archetypeKey,
prefill,
- requestArchetype,
type ArchetypeList,
} from "./CreateAgentArchetype.js";
import "./CreateAgentForm.css";
@@ -231,7 +230,6 @@ export function CreateAgentForm({
permissions: catalogue
? requestPermissions(selected, catalogue.default)
: undefined,
- archetype: requestArchetype(picked),
}),
});
if (!r.ok) {
@@ -323,9 +321,7 @@ export function CreateAgentForm({
/>
{picked && (
- {picked.description} An agent created from an archetype has
- no config repo: its hive builds it from the archetype's
- module.
+ {picked.description}
)}
>
@@ -400,9 +396,7 @@ export function CreateAgentForm({
Submitting this queues everything a new agent needs: a swarm-level
identity, a config repo on the forge with the operator added as a
collaborator, and a container running the agent on the hive you pick
- above. An agent created from an archetype gets no config repo: its
- container runs the archetype's module. Watch it all settle on{" "}
- jobs.
+ above. Watch it all settle on jobs.
diff --git a/frontend/packages/swarm-ui/test/create-agent-archetype.test.mjs b/frontend/packages/swarm-ui/test/create-agent-archetype.test.mjs
index e6d3d0ca..fb884822 100644
--- a/frontend/packages/swarm-ui/test/create-agent-archetype.test.mjs
+++ b/frontend/packages/swarm-ui/test/create-agent-archetype.test.mjs
@@ -2,11 +2,7 @@
// Run by `npm test` with Node's type stripping.
import assert from "node:assert/strict";
import { test } from "node:test";
-import {
- archetypeKey,
- prefill,
- requestArchetype,
-} from "../src/pages/CreateAgentArchetype.ts";
+import { archetypeKey, prefill } from "../src/pages/CreateAgentArchetype.ts";
const defaults = ["messaging", "meta", "inbox", "execution"];
@@ -69,17 +65,3 @@ test("the key tells sources apart", () => {
archetypeKey({ source: "b", name: "x", description: "" }),
);
});
-
-test("a picked archetype is sent by source and name, none is left out", () => {
- const reviewer = {
- source: "hyperhive",
- name: "reviewer",
- description: "reviews",
- permissions: ["messaging"],
- };
- assert.deepEqual(requestArchetype(reviewer), {
- source: "hyperhive",
- name: "reviewer",
- });
- assert.equal(requestArchetype(undefined), undefined);
-});
diff --git a/hive-agent/prompts/system.md b/hive-agent/prompts/system.md
index c3dd9e95..18bba8de 100644
--- a/hive-agent/prompts/system.md
+++ b/hive-agent/prompts/system.md
@@ -3,24 +3,13 @@ You are hyperhive agent `{label}` (qualified: `{qualified_label}`){hive_identity
Tools (hyperhive surface). Full signature + behavior for each comes from the tool's own MCP description (you already received it via the MCP tool schema) — this is just the map of what exists and which ones are gated, so you know where to look:
- **Inbox / messaging** (always available): `mcp__hyperhive__recv`, `mcp__hyperhive__ack_until`, `mcp__hyperhive__send`, `mcp__hyperhive__get_loose_ends`, `mcp__hyperhive__cancel_loose_end`, `mcp__hyperhive__mark_todos_done`, `mcp__hyperhive__remind`, `mcp__hyperhive__set_status`, `mcp__hyperhive__get_agent_meta`. `send` reaches peers on this hive only; **reach the operator over matrix** if you have the matrix MCP tools (`mcp__matrix__send_dm` or `mcp__matrix__send_message`); without them the operator reads your `set_status` line and turn output on the dashboard, and your logs. `send(to: "operator")` is refused. One habit worth internalizing beyond the tool descriptions themselves: prefer ending the turn over repeatedly polling `recv` when idle (only turn-boundaries observe in-container todo wakes — bash-task completions, matrix unread, forge activity — and ending the turn is also your checkpoint). For a large todo backlog (`get_loose_ends` caps at 40 rows), clear reviewed ids in bulk with `mark_todos_done` rather than cancelling one at a time — there's no blind range-clear, only ids you've actually looked at.
-- **Extra MCP tools** (some agents only): `mcp____` — agent-specific (matrix client, scraper, db connector, etc.) declared in your NixOS config under `services.hyperhive.agent.extraMcpServers`. First-class tools, already operator-approved at deploy time.
-
-
+- **Extra MCP tools** (some agents only): `mcp____` — agent-specific (matrix client, scraper, db connector, etc.) declared in your `agent.nix` under `services.hyperhive.agent.extraMcpServers`. First-class tools, already operator-approved at deploy time.
Need new packages, env vars, or other NixOS config for yourself? You can't edit your own config directly — open a PR on your `agent-configs/` repo, or contact the operator directly. Config repos live at `/agents/{label}/config/` (read-only inside your container). All changes flow through operator-approved commits.
Your config repo is mounted **read-only** at `/agents/{label}/config/` — `agent.nix` plus whatever extra files define you (declared packages, env vars, MCP servers). Read it to see exactly what defines you before asking for a change, so you can point at the precise file and line.
-_Changing_ any agent's config is not a tool call at all — it's a forge PR on the agent's `agent-configs/` repo, which an operator reviews and merges on the forge; the merge deploys it.
-
-
-
-
-You are built from the `{archetype}` archetype and have no config repo of your own: there is no `agent-configs/` repo for you, and `/agents/{label}/config/` is empty. Need new packages, env vars, or other NixOS config for yourself? Ask the operator: what defines you is the archetype, shared with every agent built from it.
-
-
-
-Operator boundary: starting, stopping and rebuilding containers is the operator's — ask them when any agent needs one. _Creating_ a new agent is not something you can do from here — ask the operator, who creates agents at swarm level. The operator only signs off on changes; you run the day-to-day.
+Operator boundary: starting, stopping and rebuilding containers is the operator's — ask them when any agent needs one. _Creating_ a new agent is not something you can do from here — ask the operator, who scaffolds the new agent's config repo and spawns it from the dashboard. _Changing_ any agent's config is not a tool call at all — it's a forge PR on the agent's `agent-configs/` repo, which an operator reviews and merges on the forge; the merge deploys it. The operator only signs off on changes; you run the day-to-day.
Messages from sender `system` are hyperhive helper events (JSON body, `event` field discriminates): `container_crash`, `needs_update`. Use these to react to lifecycle changes:
diff --git a/hive-agent/src/prompt.rs b/hive-agent/src/prompt.rs
index 4d865040..5dccb8ea 100644
--- a/hive-agent/src/prompt.rs
+++ b/hive-agent/src/prompt.rs
@@ -1,6 +1,6 @@
//! System-prompt renderer. Single `prompts/system.md` with
-//! HTML-comment markers gating role-specific and config-repo-specific
-//! blocks; this module assembles the final prompt (always "agent" role — there is only one
+//! HTML-comment markers gating role-specific blocks; this module
+//! assembles the final prompt (always "agent" role — there is only one
//! role). Marker grammar + placeholder substitution rules in
//! `docs/turn-loop/claude-invocation.md::On-boot files` (`claude-system-prompt.md`).
@@ -32,7 +32,7 @@ pub fn render(
docs_dir: Option<&str>,
operators: &[OperatorProfile],
) -> String {
- let body = filter_blocks(template, "role", "agent");
+ let body = filter_role_blocks(template, "agent");
let qualified = crate::identity::qualify(label);
let hive_identity = hive_name
.filter(|n| !n.is_empty())
@@ -118,27 +118,27 @@ async fn within_timeout(
}
}
-/// Walk `template` line-by-line, stripping `` /
-/// `` marker lines and suppressing the lines inside a block
-/// unless `X == target`. A close marker ends the current block. Markers of
-/// any other kind are left in place, for the pass that filters that kind.
-/// Two kinds exist: `role` (always `agent`; the grammar stays wired for a
-/// future manager / multi-role prompt) and `config` ([`config_blocks`]).
-fn filter_blocks(template: &str, kind: &str, target: &str) -> String {
+/// Walk `template` line-by-line, stripping `` /
+/// `` marker lines and suppressing the lines inside a block
+/// unless `X == target`. A close marker ends the current block. Production
+/// `system.md` carries no markers today (single agent role — see the module
+/// doc), so this is effectively a passthrough; the marker grammar stays wired
+/// for a future manager / multi-role prompt.
+fn filter_role_blocks(template: &str, target: &str) -> String {
let mut out = String::with_capacity(template.len());
- // None = outside any block; Some(value) = inside a block of this kind.
- let mut active: Option<&str> = None;
+ // None = outside any block; Some(role) = inside role-tagged block.
+ let mut active_role: Option<&str> = None;
for line in template.lines() {
let trimmed = line.trim();
- if let Some(value) = parse_open_marker(trimmed, kind) {
- active = Some(value);
+ if let Some(role) = parse_open_marker(trimmed) {
+ active_role = Some(role);
continue;
}
- if parse_close_marker(trimmed, kind).is_some() {
- active = None;
+ if parse_close_marker(trimmed).is_some() {
+ active_role = None;
continue;
}
- if active.is_none_or(|value| value == target) {
+ if active_role.is_none_or(|role| role == target) {
out.push_str(line);
out.push('\n');
}
@@ -146,37 +146,23 @@ fn filter_blocks(template: &str, kind: &str, target: &str) -> String {
out
}
-/// `template` with its `config:repo` blocks for a custom agent, or its
-/// `config:archetype` blocks and `{archetype}` filled in for an agent built
-/// from `archetype`. An empty name is a custom agent.
-fn config_blocks(template: &str, archetype: Option<&str>) -> String {
- match archetype.filter(|a| !a.is_empty()) {
- Some(name) => filter_blocks(template, "config", "archetype").replace("{archetype}", name),
- None => filter_blocks(template, "config", "repo"),
- }
-}
-
-/// `` with `kind = "role"` → `Some("agent")`. Anything
-/// else returns None. Whitespace inside the marker is tolerated so a future
+/// `` → `Some("agent")`. Anything else returns
+/// None. Whitespace inside the marker is tolerated so a future
/// author's `` (no spaces) still parses; the dashboard
-/// markdown renderer is equally lenient. Close tags (`/role:...`) can't
-/// accidentally match — the `strip_prefix(kind)` rejects the leading slash
-/// before we'd ever see it.
-fn parse_open_marker<'a>(line: &'a str, kind: &str) -> Option<&'a str> {
+/// markdown renderer is equally lenient. Close tags (`/role:...`)
+/// can't accidentally match — the `strip_prefix("role:")` rejects
+/// the leading slash before we'd ever see it.
+fn parse_open_marker(line: &str) -> Option<&str> {
let inside = line.strip_prefix("")?.trim();
- let value = inside.strip_prefix(kind)?.strip_prefix(':')?.trim();
- Some(value)
+ let role = inside.strip_prefix("role:")?.trim();
+ Some(role)
}
-/// `` with `kind = "role"` → `Some("agent")`. Mirror of
+/// `` → `Some("agent")`. Mirror of
/// [`parse_open_marker`] for the closing tag.
-fn parse_close_marker<'a>(line: &'a str, kind: &str) -> Option<&'a str> {
+fn parse_close_marker(line: &str) -> Option<&str> {
let inside = line.strip_prefix("")?.trim();
- inside
- .strip_prefix('/')?
- .strip_prefix(kind)?
- .strip_prefix(':')
- .map(str::trim)
+ inside.strip_prefix("/role:").map(str::trim)
}
/// Write the assembled prompt to a stable path next to the harness
@@ -210,9 +196,6 @@ pub async fn write_system_prompt(_socket: &Path, label: &str) -> Result
let docs_dir = std::env::var("HIVE_DOCS_DIR")
.ok()
.filter(|d| !d.is_empty());
- // The meta flake sets HIVE_ARCHETYPE on an agent built from an archetype,
- // which has no config repo of its own.
- let template = config_blocks(&template, std::env::var("HIVE_ARCHETYPE").ok().as_deref());
let body = render(
&template,
label,
@@ -274,7 +257,7 @@ shared closer
#[test]
fn filter_keeps_shared_and_target_role() {
- let agent = filter_blocks(SAMPLE, "role", "agent");
+ let agent = filter_role_blocks(SAMPLE, "agent");
assert!(agent.contains("shared opener"));
assert!(agent.contains("agent-only line"));
assert!(!agent.contains("manager-only line"));
@@ -285,7 +268,7 @@ shared closer
#[test]
fn filter_for_manager_picks_manager_block() {
- let manager = filter_blocks(SAMPLE, "role", "manager");
+ let manager = filter_role_blocks(SAMPLE, "manager");
assert!(manager.contains("shared opener"));
assert!(!manager.contains("agent-only line"));
assert!(manager.contains("manager-only line"));
@@ -295,38 +278,23 @@ shared closer
#[test]
fn parse_open_marker_handles_whitespace_variants() {
- assert_eq!(
- parse_open_marker("", "role"),
- Some("agent")
- );
- assert_eq!(
- parse_open_marker("", "role"),
- Some("agent")
- );
- assert_eq!(
- parse_open_marker("", "role"),
- Some("manager")
- );
+ assert_eq!(parse_open_marker(""), Some("agent"));
+ assert_eq!(parse_open_marker(""), Some("agent"));
+ assert_eq!(parse_open_marker(""), Some("manager"));
// Close tags must NOT match open-tag parser.
- assert_eq!(parse_open_marker("", "role"), None);
+ assert_eq!(parse_open_marker(""), None);
// Non-markers pass through (return None).
- assert_eq!(parse_open_marker("just text", "role"), None);
- assert_eq!(parse_open_marker("", "role"), None);
+ assert_eq!(parse_open_marker("just text"), None);
+ assert_eq!(parse_open_marker(""), None);
}
#[test]
fn parse_close_marker_handles_whitespace_variants() {
- assert_eq!(
- parse_close_marker("", "role"),
- Some("agent")
- );
- assert_eq!(
- parse_close_marker("", "role"),
- Some("manager")
- );
+ assert_eq!(parse_close_marker(""), Some("agent"));
+ assert_eq!(parse_close_marker(""), Some("manager"));
// Open tags must NOT match close-tag parser.
- assert_eq!(parse_close_marker("", "role"), None);
- assert_eq!(parse_close_marker("just text", "role"), None);
+ assert_eq!(parse_close_marker(""), None);
+ assert_eq!(parse_close_marker("just text"), None);
}
#[test]
@@ -363,49 +331,6 @@ shared closer
assert!(rendered.contains("`/agents/alice/work/`"), "{rendered}");
}
- const CONFIG_FIXTURE: &str = "\
-shared
-
-open a PR on agent-configs
-
-
-built from `{archetype}`, no config repo
-
-";
-
- /// A custom agent gets the config-repo lines, an archetype agent the
- /// archetype lines with its name, and an empty name is a custom agent.
- #[test]
- fn config_blocks_pick_the_block_by_archetype() {
- for custom in [None, Some("")] {
- let picked = config_blocks(CONFIG_FIXTURE, custom);
- assert!(picked.contains("open a PR on agent-configs"), "{picked}");
- assert!(!picked.contains("no config repo"), "{picked}");
- }
- let picked = config_blocks(CONFIG_FIXTURE, Some("android-dev"));
- assert!(picked.contains("built from `android-dev`, no config repo"));
- assert!(!picked.contains("agent-configs"), "{picked}");
- assert!(picked.contains("shared"));
- assert!(!picked.contains("