Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ SKILLS_FLEET_INJECT_CONCURRENCY=5 # agents re-injected in parallel during a flee
# Pinned to a tag we bump, never a branch head — the catalog takes public PRs and
# skills carry executables. Set the URL to "" to disable the seed entirely.
# TRINITY_DEFAULT_SKILL_SOURCE=github.com/abilityai/trinity-skills
# TRINITY_DEFAULT_SKILL_SOURCE_REF=v0.2.0
# TRINITY_DEFAULT_SKILL_SOURCE_REF=v0.3.0

# ===========================================
# INSTALL PROVENANCE (#2380)
Expand Down
1 change: 1 addition & 0 deletions docs/memory/feature-flows.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

| Date | ID | Change | Flow |
|------|-----|--------|------|
| 2026-10-06 | #3123 | chore(skills): **fresh installs seed the bundled community skills catalog at `trinity-skills` v0.3.0** (was v0.2.0). The tag adds `update-dashboard`, the playbook the metrics tiles already name, and drops the four retired `add-*` installers (marketplace-only now): 38 skills. `config.DEFAULT_SKILL_SOURCE_REF`, `.env.example` and the user doc move together; `tests/unit/test_2545_skill_source_pin.py` raises its floor to v0.3.0 and adds the user doc to its parity checks. The user doc gains the steps for moving an existing instance's bundled row to a newer tag (existing installs keep their row; ent#529). No runtime code change beyond the default: the seed and the annotated-tag peel (#2550) already handle the tag. | [skills-library-sync.md](feature-flows/skills-library-sync.md) |
| 2026-10-05 | ent#752 | feat(gate): **a gated skill is refused inside the agent unless its run was approved for it** (Claude Code only). A PreToolUse hook on `Skill` and on `Agent`/`Task` skill preloads (`/opt/trinity/hooks/skill-gate.py`, its own managed-settings drop-in, exec form) asks `POST /api/skill-gate/check` with the agent's own key; the run is cleared by #751's approved-run record or a new `self_approved` record written where a self-approval lets a run through (no migration). No answer → a root-owned marker decides (gated agents fail closed, others keep working); never exit 1. A self-approved `/chat` turn runs in its own session; `/health` reports `skill_gate_hook` | [skill-gate.md](feature-flows/skill-gate.md) |
| 2026-10-05 | ent#568 | feat(delegation): **every caller is taught that a receipt means the work is running — never re-send on silence**. One text (`DELEGATION_CONTRACT`, byte-identical in `platform_prompt_service.py` and `src/mcp-server/src/delegation_contract.ts`) is spliced into the platform prompt's §Agent Collaboration and published verbatim in the `chat_with_agent` and every `chat_with_<agent>` description; `fan_out` / `send_message` repeat its rule sentence. Every `chat_with_*` `execution_id` receipt carries "Do not re-send: read the outcome with `get_execution_result(…)`", and the backend's REST "poll GET" receipts are rewritten with liveness-neutral leads. Each carrying description stays under Claude Code's 2,048-char cap — `chat_with_agent` had been cut there since #2958 | [mcp-orchestration.md](feature-flows/mcp-orchestration.md), [system-wide-trinity-prompt.md](feature-flows/system-wide-trinity-prompt.md), [mcp-agent-exposure.md](feature-flows/mcp-agent-exposure.md) |
| 2026-10-03 | #3185 | feat(a2a): **the outbound client speaks 402 — a priced remote is an outcome, not an outage**. `_read_capped` collapsed every HTTP ≥ 400 into `rpc_http_error` without reading the body, so a remote answering 402 was unreachable: the caller saw neither the price nor a way to attach a token. 402/403 on the RPC hop are now classified BEFORE the encoding and length guards (a gzipped or oversized "pay me" read as an outage), both rails are read (the HTTP 402's `payment-required` header or body, and an in-band `x402.payment.status` task — checked before `_parse_task` on send AND poll, or a priced `input-required` reaches the agent as a prompt it polls forever), and the route answers **402** with an allowlisted `detail.payment` = `{summary, x402, truncated}`, scrubbed against the token, its base64 forms and its decoded leaves. `payment_rejected` / `rpc_forbidden` stay 502 with `remote_status`, so 402 ("buy") is always distinguishable from 403 ("top up"). The endpoint credential carries a `credential_kind` (`api_key` default — every pre-#3185 record — or `payment_token`, inferred from the value when omitted with the SAME predicate the client sends on), an x402 v3 token is flagged `credential_single_use` rather than refused, and the MCP tools return `payment_required` + `payment` + `task_id` + `do_not_retry` with a description that names who can act. Trinity never buys, never retries a priced call, and never snapshots a 402 — a stored one would replay "pay me" after the operator paid | [a2a-outbound-call.md](feature-flows/a2a-outbound-call.md), [architecture/backend.md](architecture/backend.md), [architecture/mcp-server.md](architecture/mcp-server.md) |
Expand Down
5 changes: 3 additions & 2 deletions docs/memory/feature-flows/skills-library-sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,7 @@ CREATE TABLE IF NOT EXISTS system_settings (

| Date | Changes |
|------|---------|
| 2026-10-06 | **#3123**: bundled community-catalog pin bumped to `trinity-skills` **v0.3.0** (fresh-install seed only). The catalog gains `update-dashboard`, the playbook the metrics tiles already point users at, and drops the four retired `add-*` installers (now marketplace-only), giving 38 skills. The guard floor rises to v0.3.0, and `docs/user-docs/automation/skills-and-playbooks.md` joins `.env.example` in the parity check. Existing instances keep their row (ent#529); that user doc now carries the steps for moving one to a newer tag (`PUT /api/skills/sources/{id}`, then a full sync). |
| 2026-09-30 | **ent#672**: the listing the sync produces now carries each skill's lifecycle keys — `deprecated` and `superseded_by` (the library's `superseded-by`) — parsed on every listing, never persisted, so a re-sync that drops the key clears the flag. Contract details: [skill-injection.md](skill-injection.md). |
| 2026-09-06 | **#2545 + #2550**: bundled community-catalog pin bumped to `trinity-skills` **v0.2.0** (fresh-install seed only — adds the `project-management` category, 14 skills; `.env.example` documents the same value, `tests/unit/test_2545_skill_source_pin.py` keeps them in step). Update-path tag pin now compares the tag **peeled** (`refs/tags/<ref>^{commit}`): an annotated tag's bare rev-parse is the tag object, so the unmoved bundled source was refused as `moved_tag` on every sync after the first (`tests/unit/test_2550_annotated_tag_pin.py`, both tag kinds). |
| 2026-07-29 | **ent#236 lifecycle automation**: scheduled leader-locked auto-sync, commit-gated fleet-wide re-inject with an honest per-agent report, durable sync status (`--workers 2` gap), and the dedicated range-validated `GET/PUT /api/settings/skills-library` route. Removal-on-unassign is documented in [skill-injection.md](skill-injection.md). |
Expand All @@ -716,5 +717,5 @@ CREATE TABLE IF NOT EXISTS system_settings (

---

**Last Updated**: 2026-09-30
**Status**: Verified - Updated for ent#672 lifecycle keys on the listing
**Last Updated**: 2026-10-06
**Status**: Verified - Updated for #3123 bundled catalog pin v0.3.0
14 changes: 13 additions & 1 deletion docs/user-docs/automation/skills-and-playbooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,19 @@ Existing repositories keep working with no configuration. The resolved root is r

Skills carry executable `scripts/`, and library automation can push them to your whole fleet unattended. So:

- The bundled **community source is pinned to a tag**, not a branch head — currently `v0.2.0` of `trinity-skills`. New upstream commits do not reach your fleet until the tag is bumped and you sync. The pin is a fresh-install seed: an existing instance keeps the source row it already has. To move it to a newer tag, an admin updates the source's ref through `PUT /api/skills/sources/{id}` (the Settings panel adds, syncs, disables, and removes sources but does not edit a ref in place) or removes the source and adds it again with the new tag. `TRINITY_DEFAULT_SKILL_SOURCE_REF` in `.env` changes the tag a fresh install is seeded with; `TRINITY_DEFAULT_SKILL_SOURCE=""` disables the seed entirely.
- The bundled **community source is pinned to a tag**, not a branch head — currently `v0.3.0` of `trinity-skills`. New upstream commits do not reach your fleet until the tag is bumped and you sync. The pin is a fresh-install seed: an existing instance keeps the source row it already has. To move it to a newer tag, an admin updates the source's ref through `PUT /api/skills/sources/{id}` (the Settings panel adds, syncs, disables, and removes sources but does not edit a ref in place) — the steps are below. Removing the source and adding it again with the new tag is **not** equivalent: a source added through `POST /api/skills/sources` is always a custom source, so it loses the bundled badge and gets the custom-source priority, which can change which source wins when two sources ship a skill with the same name. `TRINITY_DEFAULT_SKILL_SOURCE_REF` in `.env` changes the tag a fresh install is seeded with; `TRINITY_DEFAULT_SKILL_SOURCE=""` disables the seed entirely.

**Moving an existing instance to a newer catalog tag** (replace `<tag>` with the tag you are moving to):

1. **Before you move.** A newer tag can drop skills — for example, `v0.3.0` dropped the four `add-*` installers (`add-backlog`, `add-project-management`, `add-canon`, `add-orchestrator`). An agent still assigned a dropped skill keeps its old files, but every later delivery reports "Skill not found in library". Unassign those skills first. An agent that still needs one can get it from the abilities marketplace as `/agent-dev:<name>` — a marketplace plugin, outside the Library.
2. **Find the bundled row.** With an admin token (`POST /api/token`; agent MCP keys are refused), call `GET /api/skills/sources` and find the entry in `sources` with `"is_default": true`. Note its `id`, and its current `ref` for rollback.
- No such row (an instance migrated from the legacy single-repository setting, or one where the bundled source was removed): add the catalog as a custom source pinned to the tag instead (Settings → **Track: Tag**).
- The row is disabled: enable it.
3. **Change the ref.** `PUT /api/skills/sources/{id}` with `{"ref": "<tag>"}`. Changing the ref resets the source's sync status to `never`.
4. **Sync the whole library.** Use **Sync all** in the Settings skill-sources panel or **Sync now** on the Library's Skills tab (both call `POST /api/skills/library/sync`), not the per-source **Sync** button. Only the full sync starts the fleet re-inject, and only when automatic re-inject is on; a per-source sync leaves running agents on their old files. If scheduled auto-sync is enabled, it also picks up the change on its next run and may re-inject across the fleet. If a per-source **Sync** has already run on the new tag, a full sync — manual or scheduled — finds that source unchanged and starts no re-inject (unless another source also moved) — restart the affected agents, since an agent's skills are delivered again when it starts, or re-deliver one agent's skills with `POST /api/agents/{name}/skills/inject`.
5. **Check.** Confirm the skills you expect from the new tag are in the Library (for `v0.3.0`, `update-dashboard`).

**Rollback:** the same `PUT` with the `ref` you noted, then sync the whole library again. Any agent assigned a skill that only the newer tag carries will then report it missing.
- **Custom sources track a branch by default**, because you control who can write to them. Choose **Tag** under **Track** to pin one instead.
- **A pinned tag that moves is refused**, not adopted. If a tag now resolves to a different commit than the last sync, the sync reports `moved_tag` and leaves your fleet alone. Moving to new content means pointing the source at a new tag name — an explicit admin action. Annotated and lightweight tags are both compared by the commit they point at, so a release tag that has not moved is never refused.

Expand Down
8 changes: 5 additions & 3 deletions src/backend/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,16 +528,18 @@
# quiet (a failed row in Settings), not loud. Bump this in lockstep with the
# catalog's releases — the seed is fresh-install only, so a bump reaches new
# installs and nothing else (#2545 moved it to v0.2.0, the release that added
# the project-management category; `.env.example` documents the same value and
# `tests/unit/test_2545_skill_source_pin.py` keeps the two in step). The env
# the project-management category; #3123 to v0.3.0, the release that added
# `update-dashboard`, which the metrics tiles point users at; `.env.example` and
# `docs/user-docs/automation/skills-and-playbooks.md` state the same value and
# `tests/unit/test_2545_skill_source_pin.py` keeps the three in step). The env
# var is the escape hatch for an instance that wants an older or newer catalog.
#
# TRINITY_DEFAULT_SKILL_SOURCE="" disables the seed entirely for an operator who
# wants no community catalog (mirrors TRINITY_DEFAULT_SYSTEM_MANIFEST).
DEFAULT_SKILL_SOURCE_URL = os.getenv(
"TRINITY_DEFAULT_SKILL_SOURCE", "github.com/abilityai/trinity-skills"
)
DEFAULT_SKILL_SOURCE_REF = os.getenv("TRINITY_DEFAULT_SKILL_SOURCE_REF", "v0.2.0")
DEFAULT_SKILL_SOURCE_REF = os.getenv("TRINITY_DEFAULT_SKILL_SOURCE_REF", "v0.3.0")
DEFAULT_SKILL_SOURCE_NAME = "Trinity Community Skills"

# ============================================================================
Expand Down
14 changes: 14 additions & 0 deletions tests/registry.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{
"test_files": [
{
"file": "unit/test_2545_skill_source_pin.py",
"feature": "#2545, #3123",
"added": "2026-09-06",
"updated": "2026-10-06",
"categories": [
"backend",
"skills",
"config",
"docs",
"unit"
],
"description": "Bundled community skills-catalog pin guard (static, parses SOURCE so a shell override cannot leak in): `config.DEFAULT_SKILL_SOURCE_REF` is a vX.Y.Z tag at or above the floor v0.3.0 (#3123: the first trinity-skills release with `update-dashboard`, the playbook the metrics tiles name; #2545 set v0.2.0); `.env.example` and `docs/user-docs/automation/skills-and-playbooks.md` state the same default (exactly one regex match in the doc); the fresh-install seed note reports the configured ref."
},
{
"file": "unit/test_3246_platform_alert_surfaces.py",
"feature": "#3246",
Expand Down
Loading
Loading