feat(skills): rebuild the skill system for the multi-user model
Nightly Build / build (push) Successful in 8m6s

Per blueprint/skill-project.md: the old single-namespace, hand-maintained
index is gone, replaced by a read-only, two-scope tree whose index is a
runtime function of its content.

- skills/ index generated at runtime (crates/skald-core/src/skills/:
  inventory, install, validate, watch), injected through the new
  <!-- SKILLS_LIST --> placeholder in AGENT.md (agents/common/skills.md);
  meta.json inject_skills flag removed. 11 chat/task agents carry the
  include, the 4 system agents do not.
- Two trees, both read-only in both directions: skills/shared/{id} (the
  group's) and skills/{username}/{id} (one member's own, on the stable
  userid). The root is closed too: UserFs::SkillMounts + RouteError (alias
  probe, plain-denied paths, no home fallback) and a per-user
  .skills-root/{userid} container mount with the two scope mounts nested
  inside, plus the fifth self-heal axis (skills_mounted).
- Agent verbs: skill_register/skill_delete (Config group, global scope
  behind the new skill.manage capability), fetch_repo for public repos,
  list_items(type="skills"); reads are plain read_file on the printed
  path. Seeded @fs_read skills/* allow.
- Freshness: a digest-gated watcher on the two trees emits
  SystemEvent::SkillsChanged, whose subscriber rebuilds the frozen prompt
  prefix via Skald::invalidate_prompt_prefix; in-process writers invalidate
  directly.
- The build ships no skills: the three bundled skills (ics2json,
  mcp-builder, skill-creator) and skills/index.md are removed, skills/ is
  instance data (gitignored, not packaged, no longer pruned by update.sh).
- Docs: skills.md, agents.md, shared-folders.md added; docs/index.md and
  agents/README.md updated.
This commit is contained in:
Daniele
2026-08-08 23:05:35 +01:00
parent 71e1a26b08
commit c27da4e6ab
88 changed files with 4624 additions and 9546 deletions
+32
View File
@@ -1,3 +1,35 @@
# Agents
## Adding a new agent: the skills index is opt-in
An agent sees the installed skills **only** if its `AGENT.md` carries the
`<!-- SKILLS_LIST -->` placeholder, normally through
`<!-- INCLUDE: common/skills.md -->`. There is no `meta.json` flag: the sentinel
*is* the switch, exactly as it is for `<!-- MCP_LIST -->`.
So a new agent starts **without** the index and stays without it until someone
adds the line. That is the deliberate direction of the default: the opposite one
— an agent inheriting the index by forgetfulness — is the worse failure, because
the index is written in the imperative ("you MUST read its SKILL.md") and an
unattended `type: system` agent has its approvals auto-denied and sometimes no
tools at all.
`common/skills.md` is **one line and deliberately holds no prose**, unlike
`common/mcp.md`. Every word — the imperative header, the list, the closing rules
— is produced by the renderer, so that an instance with no skills installed gets
an empty string instead of a header promising a list that isn't there. (That is
not hypothetical: the MCP section keeps its prose in the fragment, and its empty
state once had the model invent a discovery tool to fill the gap.) The fragment
cannot explain itself in place either — `resolve_includes` copies any line that
is not an upper-case sentinel straight into the prompt, so a comment there would
be read by the model.
The rule of thumb: a `chat` or `task` agent gets the include, a `system` agent
does not. Put the line **as low as possible** in the prompt (by convention right
after `common/mcp.md`) — anything above it survives in the provider's cached
prefix when a skill is added or removed. `crates/skald-core/src/agents.rs` has a
test that holds every shipped agent to this.
# Agent icons — style guide
Each agent in the `agents/` directory can have an icon/avatar declared in the `"icon"` field of its `meta.json`. The backend serves the file via `GET /api/agents/{id}/icon`.
+2
View File
@@ -75,6 +75,8 @@ To change what gets notified, edit `data/notifications.md`.
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
## System configuration
Configuration tools are hidden by default to keep context small. Call `activate_tools(["config"])` to load them when you need to manage the instance's setup — plugins, scheduled jobs, secrets — then work normally.
+2
View File
@@ -120,3 +120,5 @@ No other output — the file is the report.
---
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
+2
View File
@@ -64,3 +64,5 @@ _Date: 2026-06-03_
---
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
+1
View File
@@ -0,0 +1 @@
<!-- SKILLS_LIST -->
-1
View File
@@ -13,7 +13,6 @@
}
},
"type": "system",
"inject_skills": false,
"allow_tools": false,
"strength": "high"
}
-1
View File
@@ -13,7 +13,6 @@
}
},
"type": "system",
"inject_skills": false,
"inject_memory": ["user-memory/index.md"],
"icon": "icon.png",
"strength": "low"
+2
View File
@@ -13,3 +13,5 @@ You do NOT delegate to other agents. Do the work yourself.
---
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
+2
View File
@@ -83,6 +83,8 @@ There may be other helpers in the household's team — each good at different th
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
---
## Shared folders
-1
View File
@@ -13,7 +13,6 @@
}
},
"type": "system",
"inject_skills": false,
"inject_memory": ["user-memory/index.md"],
"icon": "icon.png",
"strength": "average"
-1
View File
@@ -13,7 +13,6 @@
}
},
"type": "system",
"inject_skills": false,
"inject_memory": ["shared-memory/index.md"],
"icon": "icon.png",
"strength": "average"
+2
View File
@@ -12,6 +12,8 @@ The user is talking to a single assistant that already knows the project. They s
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
## System configuration
Configuration tools are hidden by default to keep context small. Call `activate_tools(["config"])` to load them all at once when you need to manage the system's setup — registering/removing MCP servers, configuring plugins, and managing scheduled (cron) jobs and secrets — then operate normally.
+2
View File
@@ -116,3 +116,5 @@ If the main agent calls you again on a related topic, check if a relevant scratc
---
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
+2
View File
@@ -8,6 +8,8 @@ You are a staff-level software architect. You receive a change request, study th
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
## Available agents
Delegate work to these task specialists via `execute_task` / `execute_subtask`:
+2
View File
@@ -10,6 +10,8 @@ You work on **any file type** in any project: Rust, Swift, Python, JavaScript/Ty
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
---
## Project context
+2 -1
View File
@@ -26,7 +26,6 @@ Before writing, understand the domain:
- **Web research**: delegate complex multi-step research to `researcher` (e.g. "research best practices for offline-first iOS apps with Core Data + CloudKit sync")
- **Code analysis**: if the project already has existing code or documentation, delegate to `code-explorer` to study it and produce a structured report on the current architecture
- **Proactive MCP use**: if an MCP server could help (Wikipedia for domain background, web fetch for API docs, etc.), call `activate_tools` to activate it and use it — do not wait for instructions
- **Skills**: check `skills/index.md` — there may be reusable Python utilities for your task
### Phase 2 — Structure the Documentation
@@ -125,6 +124,8 @@ Do not wait for permission to use a tool that would clearly help.
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
## Persistent memory
<!-- INCLUDE: common/memory.md -->
+2
View File
@@ -10,6 +10,8 @@ You do **not** implement features yourself except for trivial scaffolding (creat
<!-- INCLUDE: common/mcp.md -->
<!-- INCLUDE: common/skills.md -->
## Available agents
Delegate work to these task specialists via `execute_task` / `execute_subtask`: