@jaggerxtrm/specialists 3.17.0 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +268 -134
- package/config/mandatory-rules/json-only-final-output.md +13 -0
- package/config/mandatory-rules/service-skills-diff-scan-mandatory.md +26 -0
- package/config/mandatory-rules/service-skills-gitnexus-triage.md +5 -0
- package/config/skills/setup-specialists/SKILL.md +556 -0
- package/config/skills/specialists-creator/SKILL.md +132 -4
- package/config/skills/specialists-creator/scripts/audit-spec-uniformity.mjs +1 -1
- package/config/specialists/bare.specialist.json +3 -3
- package/config/specialists/changelog-drafter.specialist.json +5 -4
- package/config/specialists/changelog-keeper.specialist.json +7 -6
- package/config/specialists/debugger.specialist.json +2 -2
- package/config/specialists/executor.specialist.json +2 -2
- package/config/specialists/explorer.specialist.json +4 -4
- package/config/specialists/memory-processor.specialist.json +3 -3
- package/config/specialists/node-coordinator.specialist.json +3 -3
- package/config/specialists/obligations-scanner.specialist.json +67 -17
- package/config/specialists/overthinker.specialist.json +3 -3
- package/config/specialists/planner.specialist.json +4 -4
- package/config/specialists/quant-methodologist.specialist.json +145 -0
- package/config/specialists/quant-researcher.specialist.json +144 -0
- package/config/specialists/researcher.specialist.json +5 -5
- package/config/specialists/reviewer.specialist.json +1 -1
- package/config/specialists/seconder.specialist.json +2 -2
- package/config/specialists/security-auditor.specialist.json +2 -2
- package/config/specialists/service-skills-sync.specialist.json +90 -75
- package/config/specialists/specialists-creator.specialist.json +4 -4
- package/config/specialists/sync-docs.specialist.json +4 -4
- package/config/specialists/test-engineer.specialist.json +3 -3
- package/config/specialists/test-runner.specialist.json +7 -7
- package/config/specialists/transcriber.specialist.json +3 -3
- package/config/specialists/xt-merge.specialist.json +4 -4
- package/dist/asset-contract.json +21 -2
- package/dist/index.js +25704 -16376
- package/dist/lib.js +9849 -6147
- package/dist/types/cli/console/components.d.ts +83 -0
- package/dist/types/cli/console/components.d.ts.map +1 -0
- package/dist/types/cli/console/config-source.d.ts +58 -0
- package/dist/types/cli/console/config-source.d.ts.map +1 -0
- package/dist/types/cli/console/forensic.d.ts +11 -0
- package/dist/types/cli/console/forensic.d.ts.map +1 -0
- package/dist/types/cli/console/git.d.ts +28 -0
- package/dist/types/cli/console/git.d.ts.map +1 -0
- package/dist/types/cli/console/help.d.ts +2 -0
- package/dist/types/cli/console/help.d.ts.map +1 -0
- package/dist/types/cli/console/log.d.ts +13 -0
- package/dist/types/cli/console/log.d.ts.map +1 -0
- package/dist/types/cli/console/repo-config.d.ts +26 -0
- package/dist/types/cli/console/repo-config.d.ts.map +1 -0
- package/dist/types/cli/console/repo-discovery.d.ts +12 -0
- package/dist/types/cli/console/repo-discovery.d.ts.map +1 -0
- package/dist/types/cli/console/runtime.d.ts +12 -0
- package/dist/types/cli/console/runtime.d.ts.map +1 -0
- package/dist/types/cli/console/subscribe-prototype.d.ts +18 -0
- package/dist/types/cli/console/subscribe-prototype.d.ts.map +1 -0
- package/dist/types/cli/console/theme.d.ts +91 -0
- package/dist/types/cli/console/theme.d.ts.map +1 -0
- package/dist/types/cli/console/types.d.ts +231 -0
- package/dist/types/cli/console/types.d.ts.map +1 -0
- package/dist/types/cli/console/view-model.d.ts +252 -0
- package/dist/types/cli/console/view-model.d.ts.map +1 -0
- package/dist/types/cli/console.d.ts +2 -0
- package/dist/types/cli/console.d.ts.map +1 -0
- package/dist/types/cli/db.d.ts.map +1 -1
- package/dist/types/cli/doctor.d.ts.map +1 -1
- package/dist/types/cli/edit.d.ts.map +1 -1
- package/dist/types/cli/epic.d.ts.map +1 -1
- package/dist/types/cli/feed.d.ts.map +1 -1
- package/dist/types/cli/forensic.d.ts +2 -0
- package/dist/types/cli/forensic.d.ts.map +1 -0
- package/dist/types/cli/format-helpers.d.ts +4 -2
- package/dist/types/cli/format-helpers.d.ts.map +1 -1
- package/dist/types/cli/help.d.ts.map +1 -1
- package/dist/types/cli/init.d.ts +10 -0
- package/dist/types/cli/init.d.ts.map +1 -1
- package/dist/types/cli/list.d.ts.map +1 -1
- package/dist/types/cli/log.d.ts.map +1 -1
- package/dist/types/cli/metrics.d.ts +2 -0
- package/dist/types/cli/metrics.d.ts.map +1 -0
- package/dist/types/cli/ps.d.ts.map +1 -1
- package/dist/types/cli/result.d.ts.map +1 -1
- package/dist/types/cli/run.d.ts +1 -0
- package/dist/types/cli/run.d.ts.map +1 -1
- package/dist/types/cli/script.d.ts +3 -0
- package/dist/types/cli/script.d.ts.map +1 -1
- package/dist/types/cli/serve.d.ts.map +1 -1
- package/dist/types/cli/setup.d.ts +19 -1
- package/dist/types/cli/setup.d.ts.map +1 -1
- package/dist/types/cli/status.d.ts.map +1 -1
- package/dist/types/cli/version-check.d.ts +1 -0
- package/dist/types/cli/version-check.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/pi/session.d.ts +11 -1
- package/dist/types/pi/session.d.ts.map +1 -1
- package/dist/types/server.d.ts +15 -0
- package/dist/types/server.d.ts.map +1 -1
- package/dist/types/specialist/benchmarks.d.ts +37 -0
- package/dist/types/specialist/benchmarks.d.ts.map +1 -0
- package/dist/types/specialist/chain-identity.d.ts +7 -1
- package/dist/types/specialist/chain-identity.d.ts.map +1 -1
- package/dist/types/specialist/control.d.ts.map +1 -1
- package/dist/types/specialist/forensic-events.d.ts +138 -0
- package/dist/types/specialist/forensic-events.d.ts.map +1 -0
- package/dist/types/specialist/forensic-renderer.d.ts +34 -0
- package/dist/types/specialist/forensic-renderer.d.ts.map +1 -0
- package/dist/types/specialist/git-diff-evidence.d.ts +28 -0
- package/dist/types/specialist/git-diff-evidence.d.ts.map +1 -0
- package/dist/types/specialist/global-config.d.ts +389 -0
- package/dist/types/specialist/global-config.d.ts.map +1 -0
- package/dist/types/specialist/launch.d.ts +1 -0
- package/dist/types/specialist/launch.d.ts.map +1 -1
- package/dist/types/specialist/live-aggregates.d.ts +46 -0
- package/dist/types/specialist/live-aggregates.d.ts.map +1 -0
- package/dist/types/specialist/loader.d.ts +50 -1
- package/dist/types/specialist/loader.d.ts.map +1 -1
- package/dist/types/specialist/model-chain.d.ts +7 -0
- package/dist/types/specialist/model-chain.d.ts.map +1 -0
- package/dist/types/specialist/model-probes.d.ts +28 -0
- package/dist/types/specialist/model-probes.d.ts.map +1 -0
- package/dist/types/specialist/node-contract.d.ts +18 -18
- package/dist/types/specialist/node-supervisor.d.ts.map +1 -1
- package/dist/types/specialist/observability-db.d.ts +1 -1
- package/dist/types/specialist/observability-db.d.ts.map +1 -1
- package/dist/types/specialist/observability-sqlite.d.ts +25 -0
- package/dist/types/specialist/observability-sqlite.d.ts.map +1 -1
- package/dist/types/specialist/preset-resolver.d.ts +56 -0
- package/dist/types/specialist/preset-resolver.d.ts.map +1 -0
- package/dist/types/specialist/prometheus-projection.d.ts +25 -0
- package/dist/types/specialist/prometheus-projection.d.ts.map +1 -0
- package/dist/types/specialist/runner.d.ts +26 -1
- package/dist/types/specialist/runner.d.ts.map +1 -1
- package/dist/types/specialist/schema.d.ts +163 -54
- package/dist/types/specialist/schema.d.ts.map +1 -1
- package/dist/types/specialist/script-runner.d.ts +5 -1
- package/dist/types/specialist/script-runner.d.ts.map +1 -1
- package/dist/types/specialist/snapshot-diff.d.ts +8 -0
- package/dist/types/specialist/snapshot-diff.d.ts.map +1 -0
- package/dist/types/specialist/source-queue.d.ts +13 -0
- package/dist/types/specialist/source-queue.d.ts.map +1 -0
- package/dist/types/specialist/supervisor.d.ts +15 -1
- package/dist/types/specialist/supervisor.d.ts.map +1 -1
- package/dist/types/specialist/timeline-events.d.ts +68 -1
- package/dist/types/specialist/timeline-events.d.ts.map +1 -1
- package/dist/types/tools/specialist/resume_specialist.tool.d.ts +4 -4
- package/dist/types/tools/specialist/specialist_status.tool.d.ts +1 -1
- package/dist/types/tools/specialist/steer_specialist.tool.d.ts +4 -4
- package/dist/types/tools/specialist/use_specialist.tool.d.ts +16 -16
- package/docs/ARCHITECTURE.md +1176 -0
- package/docs/TODO.md +9 -0
- package/docs/architecture.md +11 -0
- package/docs/archive/2026-03-13-bd-decision-context-template-plan.md +96 -0
- package/docs/archive/AGENT-HANDOFF.md +351 -0
- package/docs/archive/PARITY-ANALYSIS.md +296 -0
- package/docs/archive/SPECIALISTS_REFACTOR.md.md +30 -0
- package/docs/archive/cc-programmatic.md +216 -0
- package/docs/archive/claude-agent-sdk.md +594 -0
- package/docs/archive/decision-specialist-directory.md +41 -0
- package/docs/archive/discoveries.md +148 -0
- package/docs/archive/executor-benchmark-protocol.md +198 -0
- package/docs/archive/future-features.md +66 -0
- package/docs/archive/gzrx-completion-critique.md +183 -0
- package/docs/archive/gzrx-research-notes.md +401 -0
- package/docs/archive/gzrx-tool-catalog.md +760 -0
- package/docs/archive/iron-review-hardening-qa-chain-substrate.md +322 -0
- package/docs/archive/iron-review-hardening.html +1004 -0
- package/docs/archive/issuetracking.md +312 -0
- package/docs/archive/qa-v3.0.2.md +220 -0
- package/docs/archive/restructure.md +231 -0
- package/docs/archive/script-specialists.md +1254 -0
- package/docs/archive/spec-v3.md +792 -0
- package/docs/archive/specialist-stats.md +127 -0
- package/docs/archive/specialists-friction-audit.md +1347 -0
- package/docs/archive/specialists-runtime-critique.md +170 -0
- package/docs/archive/specialists-service-evaluation.md +713 -0
- package/docs/archive/specialists-substrate-alignment.md +255 -0
- package/docs/archive/substrate-review.md +1288 -0
- package/docs/archive/test-writer-specialist.md +254 -0
- package/docs/archive/using-specialists-v3-improvements-2026-05-09.md +600 -0
- package/docs/archive/xtrm-specialists-analysis.md +314 -0
- package/docs/authoring.md +701 -0
- package/docs/background-jobs.md +203 -0
- package/docs/bare-specialists.md +83 -0
- package/docs/benchmarks/executor-benchmark-runner.md +66 -0
- package/docs/bootstrap.md +161 -0
- package/docs/cli-reference.md +1645 -0
- package/docs/deploying-alongside.md +155 -0
- package/docs/design/README.md +36 -0
- package/docs/design/darth-feedor-migration.md +290 -0
- package/docs/design/roadmap/README.md +32 -0
- package/docs/design/roadmap/chain-templates/README.md +146 -0
- package/docs/design/roadmap/chain-templates/code-quick.formula.json +27 -0
- package/docs/design/roadmap/chain-templates/code-standard.formula.json +126 -0
- package/docs/design/roadmap/chain-templates/code-with-advisors.formula.json +128 -0
- package/docs/design/roadmap/chain-templates/code-with-tests.formula.json +76 -0
- package/docs/design/roadmap/chain-templates/debug.formula.json +128 -0
- package/docs/design/roadmap/chain-templates/doc-sync.formula.json +28 -0
- package/docs/design/roadmap/chain-templates/memory-hygiene.formula.json +27 -0
- package/docs/design/roadmap/chain-templates/planning.formula.json +27 -0
- package/docs/design/roadmap/chain-templates/premortem.formula.json +26 -0
- package/docs/design/roadmap/chain-templates/release-prep.formula.json +36 -0
- package/docs/design/roadmap/chain-templates/research-only.formula.json +28 -0
- package/docs/design/roadmap/chain-templates/restitch.formula.json +125 -0
- package/docs/design/roadmap/chain-templates/security-deep.formula.json +161 -0
- package/docs/design/roadmap/chain-templates/test-only.formula.json +52 -0
- package/docs/design/roadmap/chain-templates/triage.formula.json +35 -0
- package/docs/design/roadmap/history/handoff-from-substrate-design.md +87 -0
- package/docs/design/roadmap/history/substrate-reconciliation.md +105 -0
- package/docs/design/roadmap/specialists-roadmap.md +1193 -0
- package/docs/design/sp-console-subscribe-via-materializer.md +231 -0
- package/docs/design/sp-console-tui-mock-v2.html +293 -0
- package/docs/design/sp-console-tui-mock.html +120 -0
- package/docs/design/sp-console-tui.md +340 -0
- package/docs/design/specialist-agentops-suite.md +323 -0
- package/docs/design/substrate/channels.md +14 -0
- package/docs/design/substrate/devops-platform-engineering-prd.md +446 -0
- package/docs/design/substrate/html-design-example.md +339 -0
- package/docs/design/xtrm-tiers-architecture.svg +132 -0
- package/docs/devops/dependency-verdict-materialization.md +46 -0
- package/docs/epic-readiness.md +75 -0
- package/docs/examples/mercury-atomic-summarizer.specialist.json +26 -0
- package/docs/examples/smoke-echo-text-expected-keys.specialist.json +25 -0
- package/docs/examples/smoke-echo.specialist.json +25 -0
- package/docs/features.md +1577 -0
- package/docs/hooks.md +81 -0
- package/docs/installation.md +142 -0
- package/docs/manifest.md +184 -0
- package/docs/mcp-servers.md +73 -0
- package/docs/mcp-tools.md +71 -0
- package/docs/nodes.md +231 -0
- package/docs/observability-metrics.md +152 -0
- package/docs/operator/sp-console-v2-walkthrough.md +410 -0
- package/docs/overrides-guide.md +306 -0
- package/docs/pi-rpc-boundary.md +118 -0
- package/docs/pi-session.md +195 -0
- package/docs/release.md +22 -0
- package/docs/skills.md +132 -0
- package/docs/specialists/handoff-schema.md +181 -0
- package/docs/specialists-catalog.md +99 -0
- package/docs/specialists-service-install.md +226 -0
- package/docs/specialists-service.md +363 -0
- package/docs/surface-ownership.md +138 -0
- package/docs/upgrade-notes/kan-90-global-user-config.md +114 -0
- package/docs/upgrade-notes/kan-91-expanded-overrides.md +261 -0
- package/docs/workflow.md +114 -0
- package/docs/worktree.md +71 -0
- package/docs/worktrees.md +309 -0
- package/package.json +6 -3
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Specialist Authoring
|
|
3
|
+
scope: authoring
|
|
4
|
+
category: guide
|
|
5
|
+
version: 1.9.2
|
|
6
|
+
updated: 2026-06-24
|
|
7
|
+
synced_at: bf6baf7a
|
|
8
|
+
description: How to write, validate, place, and maintain specialist definition files.
|
|
9
|
+
source_of_truth_for:
|
|
10
|
+
- ".xtrm/skills/active/pi/specialists-creator/SKILL.md"
|
|
11
|
+
- "src/specialist/schema.ts"
|
|
12
|
+
- "src/specialist/runner.ts"
|
|
13
|
+
- "src/pi/session.ts"
|
|
14
|
+
domain:
|
|
15
|
+
- authoring
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Specialist Authoring
|
|
19
|
+
|
|
20
|
+
This guide is the user-facing reference for authoring `.specialist.json` files. It mirrors the canonical `specialists-creator` skill and keeps examples aligned with runtime behavior.
|
|
21
|
+
|
|
22
|
+
> **Format:** All specialists use `.specialist.json`. YAML (`.specialist.yaml`) is deprecated — still loaded but prints a deprecation warning. Migrate existing YAML files to JSON.
|
|
23
|
+
|
|
24
|
+
## JSON Format Notes
|
|
25
|
+
|
|
26
|
+
- All string enum values must be quoted: `"READ_ONLY"`, `"auto"`, `"markdown"`
|
|
27
|
+
- Version must be a quoted string: `"1.0.0"` not `1.0.0`
|
|
28
|
+
- Multi-line strings use `\n` for newlines in `task_template`
|
|
29
|
+
- Comments are **not** supported in JSON — document intent in a companion `.md` file
|
|
30
|
+
- Use a JSON linter/formatter to catch syntax errors before running `specialists validate`
|
|
31
|
+
|
|
32
|
+
## Minimal skeleton
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"specialist": {
|
|
37
|
+
"metadata": {
|
|
38
|
+
"name": "my-specialist",
|
|
39
|
+
"version": "1.0.0",
|
|
40
|
+
"description": "One sentence.",
|
|
41
|
+
"category": "workflow"
|
|
42
|
+
},
|
|
43
|
+
"execution": {
|
|
44
|
+
"model": "openai-codex/gpt-5.4-mini",
|
|
45
|
+
"permission_required": "READ_ONLY"
|
|
46
|
+
},
|
|
47
|
+
"prompt": {
|
|
48
|
+
"task_template": "$prompt\n\nWorking directory: $cwd"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## `specialist.metadata` (required)
|
|
57
|
+
|
|
58
|
+
| Field | Type | Required | Notes |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `name` | string | yes | kebab-case: `[a-z][a-z0-9-]*` |
|
|
61
|
+
| `version` | string | yes | semver (`"1.0.0"`) — must be a quoted string in JSON |
|
|
62
|
+
| `description` | string | yes | one-sentence summary |
|
|
63
|
+
| `category` | string | yes | free text (`"workflow"`, `"analysis"`, `"codegen"`, …) |
|
|
64
|
+
| `author` | string | no | optional |
|
|
65
|
+
| `created` | string | no | optional date |
|
|
66
|
+
| `updated` | string | no | optional date |
|
|
67
|
+
| `tags` | string[] | no | optional labels |
|
|
68
|
+
|
|
69
|
+
## `specialist.execution` (required)
|
|
70
|
+
|
|
71
|
+
| Field | Type | Default | Notes |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `model` | string | — | required — ping before using |
|
|
74
|
+
| `fallback_model` | string | — | recommended from a different provider |
|
|
75
|
+
| `mode` | `"tool" \| "skill" \| "auto"` | `"auto"` | run mode |
|
|
76
|
+
| `timeout_ms` | number | `120000` | run timeout (ms) |
|
|
77
|
+
| `stall_timeout_ms` | number | unset | kill if no event for N ms |
|
|
78
|
+
| `max_retries` | number | `0` | retry count on failure |
|
|
79
|
+
| `interactive` | boolean | `false` | keep-alive by default for multi-turn specialists; override layers may also set it |
|
|
80
|
+
| `stdout_limit_bytes` | number | `33554432` | per-run stdout cap for script-class runtime; env `SPECIALISTS_SCRIPT_STDOUT_LIMIT_BYTES` overrides default, spec value overrides env |
|
|
81
|
+
| `response_format` | `"text" \| "json" \| "markdown"` | `"text"` | output contract hint |
|
|
82
|
+
| `expected_output_keys` | `string[]` | unset | required JSON keys the assistant output must contain; triggers required-keys check independent of `response_format` (use for text-format specs that ship a JSON contract inline in `task_template`); on miss returns `error_type: "invalid_json"` |
|
|
83
|
+
| `output_type` | enum | `"custom"` | semantic archetype: `"codegen"`, `"analysis"`, `"review"`, `"synthesis"`, `"orchestration"`, `"workflow"`, `"research"`, `"custom"` |
|
|
84
|
+
| `permission_required` | `"READ_ONLY" \| "LOW" \| "MEDIUM" \| "HIGH"` | `"READ_ONLY"` | tool-access tier |
|
|
85
|
+
| `thinking_level` | `"off" \| "minimal" \| "low" \| "medium" \| "high" \| "xhigh"` | unset | forwarded to thinking-capable models |
|
|
86
|
+
| `requires_worktree` | boolean | `true` | set `false` for workflow/script-class specialists that should not be sandboxed in a worktree |
|
|
87
|
+
| `auto_commit` | `"never" \| "checkpoint_on_waiting" \| "checkpoint_on_terminal"` | `"never"` | when to auto-commit specialist edits to the worktree |
|
|
88
|
+
| `extensions.serena` | boolean | `true` | `false` disables Serena extension injection for this specialist |
|
|
89
|
+
| `extensions.gitnexus` | boolean | `true` | `false` disables GitNexus extension injection for this specialist |
|
|
90
|
+
|
|
91
|
+
### Permission tiers
|
|
92
|
+
|
|
93
|
+
The tier coarse-grains the native pi tools your specialist gets. The full resolved tool list also includes GitNexus and Serena tools per the catalog at `.specialists/catalog/index.json` — see [manifest.md](manifest.md) for the complete picture.
|
|
94
|
+
|
|
95
|
+
| Level | Native tools added (cumulative) |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `"READ_ONLY"` | `read, grep, find, ls` |
|
|
98
|
+
| `"LOW"` | `+ bash` |
|
|
99
|
+
| `"MEDIUM"` | `+ edit` |
|
|
100
|
+
| `"HIGH"` | `+ write` |
|
|
101
|
+
|
|
102
|
+
Each tier also brings tier-appropriate GitNexus and Serena tools from the catalog. Catalog `default_overrides` may also remove native tools at runtime when extensions are healthy. To see exactly what your specialist will receive:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
sp config show <name> --resolved
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> `READ_WRITE` is **not** a valid permission value.
|
|
109
|
+
|
|
110
|
+
### Per-specialist permissions override (optional)
|
|
111
|
+
|
|
112
|
+
For most specialists the tier defaults are correct and you should not declare an override. When a specialist's policy genuinely diverges from its tier — currently only `explorer` does — add a top-level `permissions` block (sibling to `execution`):
|
|
113
|
+
|
|
114
|
+
```jsonc
|
|
115
|
+
{
|
|
116
|
+
"specialist": {
|
|
117
|
+
"execution": { "permission_required": "READ_ONLY", "...": "..." },
|
|
118
|
+
"permissions": {
|
|
119
|
+
"READ_ONLY": {
|
|
120
|
+
"denied_natives_when_extension": ["grep", "find", "ls"],
|
|
121
|
+
"denied_natives_mode": "hard"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
| Field | Type | Default | Effect |
|
|
129
|
+
|-------|------|---------|--------|
|
|
130
|
+
| `denied_natives_when_extension` | `string[]` | `[]` | Native tools to deny only when a replacement extension (gitnexus/serena) is healthy. |
|
|
131
|
+
| `denied_natives_mode` | `"soft"` \| `"hard"` | `"soft"` | `soft` keeps the tool but emits a preference hint; `hard` removes it (with health-gated restore). |
|
|
132
|
+
|
|
133
|
+
The example above is explorer's actual block: when `pi-serena-tools` and `pi-gitnexus` are loaded, native `grep`/`find`/`ls` are stripped to force the model toward `search_for_pattern`, `find_file`, `gitnexus_query`. If either extension degrades, the natives are restored automatically.
|
|
134
|
+
|
|
135
|
+
See [manifest.md](manifest.md) for full semantics, the canonical example, and when to *not* add an override.
|
|
136
|
+
|
|
137
|
+
For bare-mode authoring and npm-package starter flow, see [bare-specialists.md](bare-specialists.md).
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
### Referencing canonical assets
|
|
141
|
+
|
|
142
|
+
Custom specialists can reference package-canonical rules and skills by name instead of copying files into the repo. The runtime resolves canonical assets from the installed package when no project-local copy exists.
|
|
143
|
+
|
|
144
|
+
```jsonc
|
|
145
|
+
{
|
|
146
|
+
"specialist": {
|
|
147
|
+
"mandatory_rules": {
|
|
148
|
+
"template_sets": ["serena-cheatsheet"]
|
|
149
|
+
},
|
|
150
|
+
"skills": {
|
|
151
|
+
"paths": ["releasing"]
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Use this for stable shared guidance. Create a project-local file only when the repo intentionally changes the canonical behavior. Project/user layers still win over package canonical, so custom overlays remain explicit. See [installation.md](installation.md) for the Category A / Category B distribution split.
|
|
158
|
+
|
|
159
|
+
### Interactive precedence
|
|
160
|
+
|
|
161
|
+
Effective keep-alive order is:
|
|
162
|
+
1. explicit disable (`--no-keep-alive` / `no_keep_alive`)
|
|
163
|
+
2. explicit enable (`--keep-alive` / `keep_alive`)
|
|
164
|
+
3. JSON `execution.interactive`
|
|
165
|
+
4. default one-shot (`false`)
|
|
166
|
+
|
|
167
|
+
### Extension opt-out
|
|
168
|
+
|
|
169
|
+
Use `execution.extensions` only when specialist must skip default extension injection.
|
|
170
|
+
`false` disables injection for that specialist only.
|
|
171
|
+
|
|
172
|
+
## `specialist.prompt` (required)
|
|
173
|
+
|
|
174
|
+
| Field | Type | Required | Notes |
|
|
175
|
+
|---|---|---|---|
|
|
176
|
+
| `task_template` | string | yes | rendered with `$variables` |
|
|
177
|
+
| `system` | string | no | system prompt content |
|
|
178
|
+
| `skill_inherit` | string | no | single skill folder/file injected via `--skill` |
|
|
179
|
+
| `output_schema` | object | no | JSON schema for structured output — runner-injected, warn-only validation |
|
|
180
|
+
| `examples` | array | no | few-shot examples |
|
|
181
|
+
|
|
182
|
+
### Output contract precedence
|
|
183
|
+
|
|
184
|
+
**Order:** `response_format` → `output_type` → `output_schema`
|
|
185
|
+
|
|
186
|
+
**`response_format` behavior:**
|
|
187
|
+
- `"text"`: no report template injected (raw behavior)
|
|
188
|
+
- `"json"`: specialist must return one parseable JSON object
|
|
189
|
+
- `"markdown"`: specialist must use canonical report sections:
|
|
190
|
+
- `## Summary`, `## Status`, `## Changes`, `## Verification`, `## Risks`, `## Follow-ups`, `## Beads`
|
|
191
|
+
- Optional: `## Architecture`, `## Acceptance Criteria`, `## Machine-readable block`
|
|
192
|
+
|
|
193
|
+
**`output_type` (semantic archetype):**
|
|
194
|
+
- `"codegen"`: implementation/change manifests
|
|
195
|
+
- `"analysis"`: architecture/exploration reports
|
|
196
|
+
- `"review"`: compliance/review verdicts
|
|
197
|
+
- `"synthesis"`: decision summaries across multiple findings
|
|
198
|
+
- `"orchestration"`: coordinator actions/state handoffs
|
|
199
|
+
- `"workflow"`: procedural/operational run outputs
|
|
200
|
+
- `"research"`: source-backed findings with confidence
|
|
201
|
+
- `"custom"`: no built-in extension
|
|
202
|
+
|
|
203
|
+
**`output_schema` guidance:** Add when output must be machine-readable. Schema is injected into system prompt; post-run validation is warn-only.
|
|
204
|
+
|
|
205
|
+
**Mandatory markdown+schema rule:** If `response_format: "markdown"` and `output_schema` present, output must include `## Machine-readable block` with exactly one JSON object in a ` ```json ` fenced block matching the schema.
|
|
206
|
+
|
|
207
|
+
**Standard schemas by specialist type:**
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
// executor — change manifest
|
|
211
|
+
{
|
|
212
|
+
"prompt": {
|
|
213
|
+
"output_schema": {
|
|
214
|
+
"type": "object",
|
|
215
|
+
"properties": {
|
|
216
|
+
"status": { "enum": ["success", "partial", "failed"] },
|
|
217
|
+
"files_changed": { "type": "array", "items": { "type": "string" } },
|
|
218
|
+
"symbols_modified": { "type": "array", "items": { "type": "string" } },
|
|
219
|
+
"lint_pass": { "type": "boolean" },
|
|
220
|
+
"tests_pass": { "type": "boolean" },
|
|
221
|
+
"issues_closed": { "type": "array", "items": { "type": "string" } },
|
|
222
|
+
"follow_ups": { "type": "array", "items": { "type": "string" } }
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// explorer — analysis report
|
|
229
|
+
{
|
|
230
|
+
"prompt": {
|
|
231
|
+
"output_schema": {
|
|
232
|
+
"type": "object",
|
|
233
|
+
"properties": {
|
|
234
|
+
"summary": { "type": "string" },
|
|
235
|
+
"key_files": { "type": "array", "items": { "type": "string" } },
|
|
236
|
+
"architecture_notes": { "type": "string" },
|
|
237
|
+
"recommendations": { "type": "array", "items": { "type": "string" } }
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// planner — epic result
|
|
244
|
+
{
|
|
245
|
+
"prompt": {
|
|
246
|
+
"output_schema": {
|
|
247
|
+
"type": "object",
|
|
248
|
+
"properties": {
|
|
249
|
+
"epic_id": { "type": "string" },
|
|
250
|
+
"children": { "type": "array", "items": { "type": "string" } },
|
|
251
|
+
"test_issues": { "type": "array", "items": { "type": "string" } },
|
|
252
|
+
"first_task": { "type": "string" }
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## `specialist.skills` (optional)
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"skills": {
|
|
266
|
+
"paths": [
|
|
267
|
+
"skills/my-skill/",
|
|
268
|
+
"~/.agents/skills/domain/",
|
|
269
|
+
"skills/notes.md"
|
|
270
|
+
],
|
|
271
|
+
"scripts": [
|
|
272
|
+
{
|
|
273
|
+
"run": "./scripts/pre-check.sh",
|
|
274
|
+
"phase": "pre",
|
|
275
|
+
"inject_output": true
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"run": "bd ready",
|
|
279
|
+
"phase": "pre",
|
|
280
|
+
"inject_output": true
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"run": "./scripts/cleanup.sh",
|
|
284
|
+
"phase": "post"
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### `skills.paths`
|
|
292
|
+
- Each item is passed via `pi --skill`.
|
|
293
|
+
- Folders resolve to their `SKILL.md`.
|
|
294
|
+
- Direct file paths are accepted.
|
|
295
|
+
- Missing files are skipped silently.
|
|
296
|
+
|
|
297
|
+
### `skills.scripts`
|
|
298
|
+
- `run` accepts either:
|
|
299
|
+
- a file path (`./scripts/foo.sh`, `~/scripts/foo.sh`), or
|
|
300
|
+
- a shell command (`bd ready`, `git status`).
|
|
301
|
+
- `phase` can be `"pre"` or `"post"`.
|
|
302
|
+
- `inject_output: true` makes script stdout available as `$pre_script_output`.
|
|
303
|
+
|
|
304
|
+
### Pre/post script execution details
|
|
305
|
+
- Scripts run **locally**, outside the specialist model session.
|
|
306
|
+
- `pre` scripts run before session start.
|
|
307
|
+
- `post` scripts run after completion.
|
|
308
|
+
- Timeout is 30 seconds per script.
|
|
309
|
+
- Exit code is captured, but script failure does **not** abort the run.
|
|
310
|
+
- Pre-run validation checks:
|
|
311
|
+
- file paths exist,
|
|
312
|
+
- command binaries exist on `PATH`,
|
|
313
|
+
- obvious shebang typos are reported before launch.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## `specialist.capabilities` (optional)
|
|
318
|
+
|
|
319
|
+
Declarative capabilities help validation and tooling (`specialists doctor`, pre-run checks).
|
|
320
|
+
|
|
321
|
+
```json
|
|
322
|
+
{
|
|
323
|
+
"capabilities": {
|
|
324
|
+
"required_tools": ["bash", "read", "grep", "glob"],
|
|
325
|
+
"external_commands": ["bd", "git", "gh"]
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
| Field | Type | Behavior |
|
|
331
|
+
|---|---|---|
|
|
332
|
+
| `required_tools` | string[] | Declares required pi tools |
|
|
333
|
+
| `external_commands` | string[] | Commands validated on `PATH` before run |
|
|
334
|
+
|
|
335
|
+
If any `external_commands` binary is missing, startup hard-fails and the session does not begin.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## `specialist.output_file` (optional, top-level)
|
|
340
|
+
|
|
341
|
+
```json
|
|
342
|
+
{
|
|
343
|
+
"output_file": ".specialists/my-specialist-result.md"
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
When set, the specialist writes its **handoff block** to this file on every substantive turn — foreground and `--background`. The content is identical to what is appended to the input bead notes and shown by `sp result`: a markdown heading, the verbatim specialist output, and an italic metadata footer.
|
|
348
|
+
|
|
349
|
+
- **No env flag required.** `output_file` is honored whenever it is set (since unitAI-f58ma). It does NOT require `SPECIALISTS_JOB_FILE_OUTPUT` — that flag now only gates the debug file-mirrors (events.jsonl / status.json / result.txt).
|
|
350
|
+
- **Single writer.** In a supervised run (`sp run`) the supervisor owns the file and the runner's own write is suppressed, so the file is never double-written. (In script/serve runs there is no supervisor; the runner writes the raw output instead of the enveloped block.)
|
|
351
|
+
- **Format is the rendered handoff block, not bare output.** A downstream specialist that consumes this file as input will see the header/footer envelope around the body.
|
|
352
|
+
- **Append vs overwrite is controlled by `notes_mode`** (see below): `full-trail` appends each turn; `final-only` overwrites with just the final `[FINAL · DONE]` block.
|
|
353
|
+
- **Gitignore the path** if you don't want it committed — specs with `output_file` always write, so add the path (e.g. `.specialists/*-result.md`) to `.gitignore`.
|
|
354
|
+
|
|
355
|
+
Relative paths resolve from the working directory.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## `specialist.notes_mode`
|
|
360
|
+
|
|
361
|
+
Controls how per-turn handoff output is persisted to BOTH the input bead notes and `output_file`.
|
|
362
|
+
|
|
363
|
+
| Value | Behavior |
|
|
364
|
+
|---|---|
|
|
365
|
+
| `"full-trail"` (default) | Append every substantive turn. Bead notes / `output_file` accumulate `### … [turn N · WAITING]` blocks, ending with a final `## … [FINAL · DONE]` block. Best for keep-alive specialists where the operator wants the full trail. |
|
|
366
|
+
| `"final-only"` | Persist only the single canonical `## … [FINAL · DONE]` block; intermediate turns are skipped and `output_file` is OVERWRITTEN (not appended). Best for non-coding / chained pipelines where the next specialist reads the previous specialist's bead note or `output_file` as its input and only wants the final result. |
|
|
367
|
+
|
|
368
|
+
Empty turns are never persisted. The handoff block is markdown-native (heading + verbatim body + one italic metadata footer); the model string is normalized (provider prefix stripped, e.g. `nano-gpt/moonshotai/kimi-k2.5` renders as `kimi-k2.5`).
|
|
369
|
+
|
|
370
|
+
```json
|
|
371
|
+
{ "notes_mode": "final-only" }
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## `specialist.validation` (optional)
|
|
375
|
+
|
|
376
|
+
Used by staleness reporting in `specialists status` and `specialists list`.
|
|
377
|
+
|
|
378
|
+
| Field | Type | Notes |
|
|
379
|
+
|---|---|---|
|
|
380
|
+
| `files_to_watch` | string[] | If any watched file mtime is newer than `metadata.updated`, status becomes `STALE` |
|
|
381
|
+
| `stale_threshold_days` | number | Days before `STALE` escalates to `AGED` |
|
|
382
|
+
| `references` | array | accepted, currently unused |
|
|
383
|
+
|
|
384
|
+
### Staleness states
|
|
385
|
+
|
|
386
|
+
| State | Condition |
|
|
387
|
+
|---|---|
|
|
388
|
+
| `OK` | No watched file changed, or no watch/updated metadata configured |
|
|
389
|
+
| `STALE` | Watched file mtime > `metadata.updated` |
|
|
390
|
+
| `AGED` | `STALE` and days since `updated` > `stale_threshold_days` |
|
|
391
|
+
|
|
392
|
+
Example:
|
|
393
|
+
|
|
394
|
+
```json
|
|
395
|
+
{
|
|
396
|
+
"specialist": {
|
|
397
|
+
"metadata": {
|
|
398
|
+
"updated": "2026-03-01"
|
|
399
|
+
},
|
|
400
|
+
"validation": {
|
|
401
|
+
"files_to_watch": [
|
|
402
|
+
"src/specialist/schema.ts",
|
|
403
|
+
"src/specialist/runner.ts"
|
|
404
|
+
],
|
|
405
|
+
"stale_threshold_days": 30
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## `specialist.stall_detection` (optional)
|
|
414
|
+
|
|
415
|
+
Controls stall detection warnings during specialist execution.
|
|
416
|
+
|
|
417
|
+
| Field | Type | Default | Notes |
|
|
418
|
+
|---|---|---|---|
|
|
419
|
+
| `running_silence_warn_ms` | number | `60000` | Warn if no events for N ms while running |
|
|
420
|
+
| `running_silence_error_ms` | number | `300000` | Mark stale if no events for N ms while running |
|
|
421
|
+
| `waiting_stale_ms` | number | `3600000` | Warn if waiting state lasts N ms |
|
|
422
|
+
| `waiting_auto_close_ms` | `number \| null` | unset | ms in waiting state before attempting graceful auto-close; `null` clears inherited value |
|
|
423
|
+
| `tool_duration_warn_ms` | number | `120000` | Warn if single tool runs longer than N ms |
|
|
424
|
+
|
|
425
|
+
```json
|
|
426
|
+
{
|
|
427
|
+
"stall_detection": {
|
|
428
|
+
"running_silence_warn_ms": 60000,
|
|
429
|
+
"running_silence_error_ms": 300000,
|
|
430
|
+
"waiting_stale_ms": 3600000,
|
|
431
|
+
"waiting_auto_close_ms": null,
|
|
432
|
+
"tool_duration_warn_ms": 120000
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## `specialist.beads_integration` (optional)
|
|
440
|
+
|
|
441
|
+
| Value | Behavior |
|
|
442
|
+
|---|---|
|
|
443
|
+
| `"auto"` (default) | Create tracking bead when `permission_required` is `LOW` or higher |
|
|
444
|
+
| `"always"` | Always create a tracking bead |
|
|
445
|
+
| `"never"` | Never create a tracking bead |
|
|
446
|
+
|
|
447
|
+
`beads_write_notes` (boolean, default `true`) — when `true`, the specialist appends its handoff block to the associated bead's notes on every substantive turn. The appended block is the rendered handoff format described under `notes_mode`: a markdown heading (`### <specialist> · <model> · [turn N · WAITING]` for trail turns, `## … [FINAL · DONE]` for the final turn), the verbatim specialist output, and an italic footer with timing / token / git metadata. Set to `false` to suppress bead-note writes entirely. The same content also feeds `output_file` and `sp result` (one shared content source).
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## Built-in template variables
|
|
452
|
+
|
|
453
|
+
Always available in `prompt.task_template`:
|
|
454
|
+
|
|
455
|
+
| Variable | Value |
|
|
456
|
+
|---|---|
|
|
457
|
+
| `$prompt` | user prompt passed to the specialist |
|
|
458
|
+
| `$cwd` | current working directory (`process.cwd()`) |
|
|
459
|
+
| `$pre_script_output` | combined stdout from `pre` scripts with `inject_output: true` (empty string if none) |
|
|
460
|
+
|
|
461
|
+
When invoked with bead context (`--bead` / `bead_id`):
|
|
462
|
+
|
|
463
|
+
| Variable | Value |
|
|
464
|
+
|---|---|
|
|
465
|
+
| `$bead_context` | full bead content (used in place of plain prompt context) |
|
|
466
|
+
| `$bead_id` | bead identifier |
|
|
467
|
+
|
|
468
|
+
Custom variables can be passed at invocation with `--variables key=value` and referenced as `$key`.
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Skills injection mechanics
|
|
473
|
+
|
|
474
|
+
Files from `skills.paths` are read and appended to the system prompt at runtime.
|
|
475
|
+
|
|
476
|
+
Append format:
|
|
477
|
+
|
|
478
|
+
```text
|
|
479
|
+
---
|
|
480
|
+
# Skill: <path>
|
|
481
|
+
|
|
482
|
+
<file content>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
`prompt.skill_inherit` behaves similarly but is intended as single-file Agent Forge compatibility input and is appended under `# Service Knowledge`.
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## File placement scopes (3-tier discovery)
|
|
490
|
+
|
|
491
|
+
Specialists are discovered in priority order:
|
|
492
|
+
|
|
493
|
+
1. User (repo authoring layer): `<project-root>/.specialists/user/*.specialist.json`
|
|
494
|
+
2. Default (repo-managed mirror): `<project-root>/.specialists/default/*.specialist.json`
|
|
495
|
+
3. Package (upstream fallback): `<project-root>/config/specialists/*.specialist.json`
|
|
496
|
+
|
|
497
|
+
Legacy paths (loaded but deprecated):
|
|
498
|
+
- `<project-root>/specialists/`
|
|
499
|
+
- `<project-root>/.claude/specialists/`
|
|
500
|
+
- `<project-root>/.agent-forge/specialists/`
|
|
501
|
+
- Nested paths like `.specialists/user/specialists/`
|
|
502
|
+
|
|
503
|
+
> **User-scope CLI flag deprecated:** The `--user-dir` flag is now `--project-dir` (alias retained). User-scope discovery is project-local only; `~/.agents/specialists` is not scanned.
|
|
504
|
+
|
|
505
|
+
Name files as `<metadata.name>.specialist.json`.
|
|
506
|
+
|
|
507
|
+
> **Deprecated:** `.specialist.yaml` files are still loaded but print a deprecation warning. Migrate to `.specialist.json`.
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## Validation workflow
|
|
512
|
+
|
|
513
|
+
1. Author/update the `.specialist.json` file.
|
|
514
|
+
2. Run schema validation:
|
|
515
|
+
|
|
516
|
+
```bash
|
|
517
|
+
# Option A: CLI command (preferred)
|
|
518
|
+
specialists validate specialists/my-specialist.specialist.json
|
|
519
|
+
|
|
520
|
+
# Option B: direct schema validator
|
|
521
|
+
bun src/specialist/validate.ts specialists/my-specialist.specialist.json
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
3. Confirm discovery:
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
specialists list
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
4. Smoke test run:
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
specialists run my-specialist --prompt "ping" --no-beads
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
The validator prints `OK <file>` on success and field-level errors on failure.
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## Common errors and fixes
|
|
541
|
+
|
|
542
|
+
| Error (typical) | Cause | Fix |
|
|
543
|
+
|---|---|---|
|
|
544
|
+
| `Must be kebab-case` | `metadata.name` has spaces/uppercase | use `"my-specialist"` |
|
|
545
|
+
| `Must be semver` | version like `"v1.0"` or unquoted `1.0.0` | use `"version": "1.0.0"` |
|
|
546
|
+
| `Invalid enum value ... 'READ_WRITE'` | invalid permission tier | use `"READ_ONLY"`, `"LOW"`, `"MEDIUM"`, or `"HIGH"` |
|
|
547
|
+
| `Invalid enum value ... 'auto'` on `permission_required` | wrong enum on wrong field | use `"auto"` only for `beads_integration` |
|
|
548
|
+
| `Required` on `task_template` | missing prompt template | add `prompt.task_template` |
|
|
549
|
+
| `Required` on `model` | missing execution model | add `execution.model` |
|
|
550
|
+
| `Required` on `description` | missing metadata description | add `metadata.description` |
|
|
551
|
+
| `Required` on `category` | missing metadata category | add `metadata.category` |
|
|
552
|
+
| JSON parse error | Missing comma, trailing comma, unquoted key | Run through a JSON linter; all keys and string values must be quoted |
|
|
553
|
+
| Valid JSON but poor results | `task_template` never uses `$prompt` | include `$prompt` in template |
|
|
554
|
+
| `defaults` key unrecognized | unsupported top-level key | remove `defaults`; pass runtime values via `--variables` |
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## Context Window & Lifecycle Design
|
|
559
|
+
|
|
560
|
+
Specialists run as long-lived Pi sessions. Context management is not optional — ignoring it causes silent quality degradation before any hard limit is hit.
|
|
561
|
+
|
|
562
|
+
### Context rot starts before the window fills
|
|
563
|
+
|
|
564
|
+
Quality degrades as the context grows — compressed early context causes inconsistency, missed facts, and instruction drift. Design for bounded, coherent runs rather than arbitrarily long ones.
|
|
565
|
+
|
|
566
|
+
### Model context windows
|
|
567
|
+
|
|
568
|
+
| Model family | Context window |
|
|
569
|
+
|--------------|----------------|
|
|
570
|
+
| Gemini 3.1 Pro | 1,000,000 tokens |
|
|
571
|
+
| Qwen3.5 / GLM-5 | 128,000 tokens |
|
|
572
|
+
| Claude (all) | 200,000 tokens |
|
|
573
|
+
|
|
574
|
+
### Context health thresholds
|
|
575
|
+
|
|
576
|
+
| Utilization | Health | Action |
|
|
577
|
+
|-------------|--------|--------|
|
|
578
|
+
| < 40% | OK | Normal operation |
|
|
579
|
+
| 40–65% | MONITOR | Watch for degradation |
|
|
580
|
+
| 65–80% | WARN | Consider wrap-up |
|
|
581
|
+
| > 80% | CRITICAL | High risk of quality loss |
|
|
582
|
+
|
|
583
|
+
### Design patterns
|
|
584
|
+
|
|
585
|
+
1. **Phase-bounded runs**: Split large tasks into discrete phases with explicit completion points
|
|
586
|
+
2. **Summarization gates**: Emit structured summaries at phase boundaries for downstream context injection
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
## Script-class authoring
|
|
591
|
+
|
|
592
|
+
For specialists run through `specialists-service` (HTTP `/v1/generate` or `sp serve`).
|
|
593
|
+
|
|
594
|
+
Script-class specs are a **subset** of the full schema — same loader, same `parseSpecialist()`, but with runtime constraints enforced by the service's `compatGuard` (`src/specialist/script-runner.ts`). The schema is unchanged; what differs is which combinations the service will accept at request time.
|
|
595
|
+
|
|
596
|
+
Use this section when authoring specs for `specialists-service`. Use the rest of this guide for full agent-class specs run via `sp run`.
|
|
597
|
+
|
|
598
|
+
### Required fields (script class)
|
|
599
|
+
|
|
600
|
+
Same as for any specialist:
|
|
601
|
+
|
|
602
|
+
- `metadata.name`, `metadata.version`, `metadata.description`, `metadata.category`
|
|
603
|
+
- `execution.model` (must be resolvable from the host's `~/.pi/agent/auth.json`)
|
|
604
|
+
- `prompt.task_template`
|
|
605
|
+
|
|
606
|
+
### Constraint-marked fields (the script-class boundary)
|
|
607
|
+
|
|
608
|
+
The service rejects any spec that doesn't match these at request time with `error_type: "specialist_load_error"`:
|
|
609
|
+
|
|
610
|
+
| Field | Required value | Reason |
|
|
611
|
+
|---|---|---|
|
|
612
|
+
| `execution.interactive` | `false` | HTTP request cannot host a multi-turn keep-alive session |
|
|
613
|
+
| `execution.requires_worktree` | `false` | The service is stateless; no git branching |
|
|
614
|
+
| `execution.permission_required` | `"READ_ONLY"` | One-shot pi spawns with `--no-tools` |
|
|
615
|
+
| `execution.max_retries` | `0` (recommended) | Script-class ignores `max_retries` entirely — value has no effect. Caller (HTTP client / cron) owns retries. Set `0` so the spec's intent matches behavior. |
|
|
616
|
+
| `skills.scripts` | omitted or `[]` | Local shell hooks are a host-side capability not available in service mode |
|
|
617
|
+
|
|
618
|
+
### Optional supported fields
|
|
619
|
+
|
|
620
|
+
These run unchanged:
|
|
621
|
+
|
|
622
|
+
- `execution.timeout_ms`, `execution.fallback_model`, `execution.thinking_level`, `execution.response_format` (`"text"` | `"json"` | `"markdown"`)
|
|
623
|
+
- `prompt.system`, `prompt.output_schema`
|
|
624
|
+
- `metadata.tags`, `metadata.updated`
|
|
625
|
+
|
|
626
|
+
### Trust flags (script-class security)
|
|
627
|
+
|
|
628
|
+
By default, `compatGuard` rejects specs that would access host resources:
|
|
629
|
+
|
|
630
|
+
| Field | Default | Rejection reason |
|
|
631
|
+
|-------|---------|------------------|
|
|
632
|
+
| `skills.paths` | rejected | would inject host files into prompt |
|
|
633
|
+
| `prompt.skill_inherit` | rejected | same trust concern |
|
|
634
|
+
| `skills.scripts` | always rejected | local shell hooks unavailable in service/script mode |
|
|
635
|
+
|
|
636
|
+
To permit these fields, launch `sp serve` with trust flags:
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
sp serve --allow-skills --allow-skills-roots /safe/path:/another/safe/path
|
|
640
|
+
# Unsupported: sp serve --allow-local-scripts
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
| Flag | Effect |
|
|
644
|
+
|------|--------|
|
|
645
|
+
| `--allow-skills` | Permits `skills.paths` and `prompt.skill_inherit` |
|
|
646
|
+
| `--allow-skills-roots <p1>:<p2>:...` | Restricts permitted skill paths to entries under listed roots (requires `--allow-skills`) |
|
|
647
|
+
| `--allow-local-scripts` | Unsupported; `skills.scripts` are always rejected in service/script mode |
|
|
648
|
+
|
|
649
|
+
When `--allow-skills` is active, each skill path is resolved and hashed. The `status_json.skill_sources` field in the trace row contains `{path, sha256}` entries for audit. Unreadable files produce `sha256: 'unreadable'` rather than throwing.
|
|
650
|
+
|
|
651
|
+
> **Default-reject is intentional:** Single-tenant deployments must opt-in. Multi-tenant authn is a non-goal for v1.
|
|
652
|
+
|
|
653
|
+
### Output validation
|
|
654
|
+
|
|
655
|
+
`prompt.output_schema.required` is checked against `parsed_json` when `response_format: "json"`. Missing keys produce `error_type: "invalid_json"` with a message naming the field. Nested schema is currently warn-only; tracked in `unitAI-xutg2` (passthrough) and the deferred-strict-mode discussion in `docs/design/specialists-service-evaluation.md` §29.
|
|
656
|
+
|
|
657
|
+
#### `execution.expected_output_keys` — text-format with JSON contract
|
|
658
|
+
|
|
659
|
+
Many specs ship their JSON contract inline in `task_template` and run with `response_format: "text"` so the consumer parses the body itself. Without an explicit required-keys check, hallucinated key sets (e.g. `{command, tables}` instead of the contracted `{summary, tags}`) pass through as `success: true` and the consumer happily saves corrupt rows.
|
|
660
|
+
|
|
661
|
+
`execution.expected_output_keys: string[]` triggers a required-keys check independent of `response_format`. Set it to the keys your prompt requests:
|
|
662
|
+
|
|
663
|
+
```json
|
|
664
|
+
{
|
|
665
|
+
"specialist": {
|
|
666
|
+
"execution": {
|
|
667
|
+
"response_format": "text",
|
|
668
|
+
"expected_output_keys": ["summary", "tags"]
|
|
669
|
+
},
|
|
670
|
+
"prompt": {
|
|
671
|
+
"task_template": "Output JSON: {summary: string, tags: string[]}\n\nInput: $content"
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
Behavior:
|
|
678
|
+
|
|
679
|
+
- The runtime parses the assistant text as JSON (`stripMarkdownFences` first), then verifies every listed key is present.
|
|
680
|
+
- On miss, returns `error_type: "invalid_json"` with a message naming the missing key — the same error consumers already handle for `response_format: "json"` specs.
|
|
681
|
+
- If `response_format === "json"` is also set, the keys are unioned with `prompt.output_schema.required`.
|
|
682
|
+
- This is intentionally **not** auto-derived from `output_schema`: the cost of mistakenly validating the wrong key set is silent corruption, so authors declare expectations explicitly.
|
|
683
|
+
|
|
684
|
+
### Reference example
|
|
685
|
+
|
|
686
|
+
[`docs/examples/smoke-echo.specialist.json`](examples/smoke-echo.specialist.json) is a minimal working script-class spec. Copy it into a project's `.specialists/user/` to verify a fresh `sp serve` deployment end-to-end.
|
|
687
|
+
|
|
688
|
+
[`docs/examples/smoke-echo-text-expected-keys.specialist.json`](examples/smoke-echo-text-expected-keys.specialist.json) demonstrates the text-format-with-`expected_output_keys` pattern: ships a JSON contract inline in `task_template`, runs as `response_format: "text"`, and declares `expected_output_keys: ["summary", "tags"]` so hallucinated key sets fail with `error_type: "invalid_json"` instead of being saved.
|
|
689
|
+
|
|
690
|
+
### Same loader, same edit path
|
|
691
|
+
|
|
692
|
+
`sp edit <name> specialist.execution.model <new-model>` works identically for script-class specs — the JSON file is round-tripped, no special handling needed.
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## See also
|
|
697
|
+
|
|
698
|
+
- [specialists-catalog.md](specialists-catalog.md)
|
|
699
|
+
- [workflow.md](workflow.md)
|
|
700
|
+
- [specialists-service.md](specialists-service.md) — the HTTP service contract that consumes script-class specs
|
|
701
|
+
- [mcp-tools.md](mcp-tools.md)
|