diff --git a/.github/agents/aps-v1.1.16.agent.md b/.github/agents/aps-v1.2.1.agent.md similarity index 98% rename from .github/agents/aps-v1.1.16.agent.md rename to .github/agents/aps-v1.2.1.agent.md index 5fe4f29..563daa1 100644 --- a/.github/agents/aps-v1.1.16.agent.md +++ b/.github/agents/aps-v1.2.1.agent.md @@ -1,6 +1,6 @@ --- -name: APS v1.1.16 Agent -description: "Generate APS v1.1.16 .agent.md or .prompt.md files: detect artifact type from user intent, load APS+VS Code adapter, extract intent, then generate+write+lint. Author: Christopher Buckley. Co-authors: Juan Burckhardt, Anastasiya Smirnova. URL: https://github.com/chris-buckley/agnostic-prompt-standard" +name: APS v1.2.1 Agent +description: "Generate APS v1.2.1 .agent.md or .prompt.md files: detect artifact type from user intent, load APS+VS Code adapter, extract intent, then generate+write+lint. Author: Christopher Buckley. Co-authors: Juan Burckhardt, Anastasiya Smirnova. URL: https://github.com/chris-buckley/agnostic-prompt-standard" tools: - execute/runInTerminal - read/readFile diff --git a/.github/agents/new-feature.agent.md b/.github/agents/new-feature.agent.md index 3702b79..31febcd 100644 --- a/.github/agents/new-feature.agent.md +++ b/.github/agents/new-feature.agent.md @@ -34,12 +34,16 @@ You MUST include the check_packages helper for apt dependencies in generated ins You MUST verify installation with the binary's version command in install.sh. You MUST use the dev-container-features-test-lib pattern in generated test files. You MUST use conventional commit format for any commits. +You MUST create a feature branch from main before making any changes. +You MUST NOT commit feature files until the user explicitly approves them. +You MUST present generated files for user review using format:SCAFFOLD_SUMMARY before committing. +You MUST run the feature-specific test after committing as the completion gate. +You MUST offer to create a PR after tests pass. You MUST NOT modify unrelated files or make drive-by refactors. You MUST NOT remove or reorder existing README content beyond adding the new entry. -You MUST NOT run devcontainer features test automatically. +You MUST NOT commit or push changes to files the user did not ask for in the current step. You SHOULD read an existing feature's install.sh as a reference before generating a new one. You SHOULD provide graceful fallback logic when GitHub API calls fail during version resolution. -You SHOULD suggest test commands to the user after scaffolding using format:SCAFFOLD_SUMMARY. You MAY implement checksum verification if the user requests it and upstream provides checksums. You MAY add extra options to devcontainer-feature.json if the user specifies them. @@ -170,6 +174,7 @@ BINARY_NAME: "" REQUESTED_VERSION: "latest" SUPPORT_CHECKSUM: false RELEASE_ASSET_PATTERN: "" +TEST_RESULT: "" @@ -179,10 +184,15 @@ RELEASE_ASSET_PATTERN: "" RUN `parse-input` +RUN `create-branch` RUN `inspect-upstream` RUN `scaffold` RUN `integrate` RETURN: format="SCAFFOLD_SUMMARY" +WAIT for user approval +RUN `commit-feature` +RUN `test-feature` +RUN `create-pr` @@ -196,6 +206,10 @@ IF INP contains "checksum=true": SET SUPPORT_CHECKSUM := true (from "Agent Inference") + +USE `execute/runInTerminal` where: command="git checkout -b feat/{FEATURE_ID}" + + USE `web/githubRepo` where: query="latest release assets", repo=SOURCE_REPO CAPTURE RELEASE_ASSET_PATTERN from result @@ -226,6 +240,22 @@ USE `edit/editFiles` where: filePath=".github/workflows/test.yaml" USE `read/readFile` where: filePath="README.md" USE `edit/editFiles` where: filePath="README.md" + + +USE `execute/runInTerminal` where: command="git add -A && git commit -m 'feat: add {FEATURE_ID} dev container feature'" + + + +USE `execute/runInTerminal` where: command="devcontainer features test -f {FEATURE_ID} -i ubuntu:latest ." +CAPTURE TEST_RESULT from result +IF TEST_RESULT contains "FAILED": + TELL "Test failed. Review output and fix install.sh." level=error + + + +USE `execute/runInTerminal` where: command="git push origin feat/{FEATURE_ID}" +USE `execute/runInTerminal` where: command="gh pr create --base main --head feat/{FEATURE_ID} --title 'feat: add {FEATURE_DISPLAY_NAME} dev container feature' --fill" + diff --git a/.github/skills/agnostic-prompt-standard/SKILL.md b/.github/skills/agnostic-prompt-standard/SKILL.md index a2af341..f471e2d 100644 --- a/.github/skills/agnostic-prompt-standard/SKILL.md +++ b/.github/skills/agnostic-prompt-standard/SKILL.md @@ -7,8 +7,8 @@ metadata: author: "Christopher Buckley" co_authors: "Juan Burckhardt; Anastasiya Smirnova" spec_version: "1.0" - framework_revision: "1.1.16" - last_updated: "2026-02-18" + framework_revision: "1.2.1" + last_updated: "2026-03-12" --- # Agnostic Prompt Standard (APS) v1.0 — Skill Entry @@ -38,6 +38,9 @@ This `SKILL.md` is the **entrypoint** for the Agnostic Prompt Standard (APS) v1. - `constants-json-block-v1.0.0.example.md` - `constants-text-block-v1.0.0.example.md` - `constants-csv-block-v1.0.0.example.md` + - `composites/` — combined reference examples. + - `gui-component-spec-v1.0.0.example.md` + - `mcp-tool-bridge-v1.0.0.example.md` - `formats/` — example format blocks. - `format-code-changes-full-v1.0.0.example.md` - `format-code-map-v1.0.0.example.md` @@ -56,12 +59,16 @@ This `SKILL.md` is the **entrypoint** for the Agnostic Prompt Standard (APS) v1. - `build-skill.md` — process for building new APS-compliant skills. - `guides/` — reference documents for humans and agents. - `skill-authoring-v1.0.0.guide.md` — skill authoring reference. + - `mcp-tool-bridge-v1.0.0.guide.md` — MCP tool bridge integration guide. + - `subagent-architecture-v1.0.0.guide.md` — cross-platform subagent architecture and interface mapping guide. - `platforms/` — **non-normative** platform adapters. Each platform has a single `adaptor.md` file. - `README.md` — platforms overview and contract. - `_template/` — skeleton for new platform adapters. - `adaptor.md` - `claude-code/` — Claude Code CLI adapter. - `adaptor.md` — platform constants, tool registry, and format contracts. + - `generic/` — generic / external tools adapter. + - `adaptor.md` — neutral tool mapping guidance for MCP or other external tool layers. - `opencode/` — OpenCode adapter. - `adaptor.md` — platform constants. - `vscode-copilot/` — VS Code + GitHub Copilot adapter. @@ -72,10 +79,12 @@ This `SKILL.md` is the **entrypoint** for the Agnostic Prompt Standard (APS) v1. ## Platform adapters -Platform-specific details (file discovery, frontmatter dialects, tool naming) are documented in `platforms/`. +Platform-specific details (file discovery, frontmatter dialects, tool naming, and coordinator/worker orchestration) are documented in `platforms/`. → See [platforms/README.md](platforms/README.md) for overview and how to add new adapters. +→ See [guides/subagent-architecture-v1.0.0.guide.md](guides/subagent-architecture-v1.0.0.guide.md) for portable coordinator/worker authoring guidance. + ### VS Code + GitHub Copilot The initial adapter for VS Code + GitHub Copilot is at `platforms/vscode-copilot/`. diff --git a/.github/skills/agnostic-prompt-standard/assets/composites/mcp-tool-bridge-v1.0.0.example.md b/.github/skills/agnostic-prompt-standard/assets/composites/mcp-tool-bridge-v1.0.0.example.md new file mode 100644 index 0000000..00d3b44 --- /dev/null +++ b/.github/skills/agnostic-prompt-standard/assets/composites/mcp-tool-bridge-v1.0.0.example.md @@ -0,0 +1,112 @@ + + +# MCP tool bridge example + +This example shows how to bridge one MCP tool into APS without putting host config in the prompt. + +## 1. Raw MCP Tool (`tools/list` result) + +```json +{ + "name": "search_docs", + "title": "Search Docs", + "description": "Search the documentation site.", + "inputSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "Search text" + } + }, + "required": ["query"] + }, + "outputSchema": { + "type": "object", + "properties": { + "matches": { + "type": "array" + } + } + }, + "annotations": { + "readOnlyHint": true, + "destructiveHint": false, + "idempotentHint": true, + "openWorldHint": true + } +} +``` + +## 2. Canonical `predefinedTools.json` entry + +```json +[ + { + "name": "search_docs", + "displayName": "Search Docs", + "description": "Search the documentation site.", + "inputSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "Search text" + } + }, + "required": ["query"] + }, + "outputSchema": { + "type": "object", + "properties": { + "matches": { + "type": "array" + } + } + }, + "hints": { + "readOnly": true, + "destructive": false, + "idempotent": true, + "openWorld": true + }, + "source": { + "kind": "mcp", + "server": "docs", + "toolName": "search_docs" + } + } +] +``` + +## 3. Host alias in `config.json` + +Use `config.json` only when the host exposes a decorated runtime name. + +```json +{ + "alias": { + "mcp__docs__search_docs": "search_docs" + } +} +``` + +## 4. APS process excerpt + +```text + +USE `search_docs` where: query=QUERY +CAPTURE RESULTS from `search_docs` +RETURN: RESULTS + +``` + +## Notes + +- `search_docs` is the canonical APS tool id. +- The prompt stays neutral. It does not include transport or host config. +- The host-specific runtime name stays in external config. +- The engine can resolve the alias before tool execution. diff --git a/.github/skills/agnostic-prompt-standard/guides/subagent-architecture-v1.0.0.guide.md b/.github/skills/agnostic-prompt-standard/guides/subagent-architecture-v1.0.0.guide.md new file mode 100644 index 0000000..173cadb --- /dev/null +++ b/.github/skills/agnostic-prompt-standard/guides/subagent-architecture-v1.0.0.guide.md @@ -0,0 +1,146 @@ + +You MUST load this guide before you author coordinator and worker agents. +You MUST model portable multi-agent systems as one coordinator and one or more leaf workers. +You MUST define the worker block as the public request contract into the worker. +You MUST mirror each worker field in the caller dispatch process arguments. +You MUST define a worker response contract in and capture it in the caller. +You MUST keep platform-specific invocation syntax inside the caller dispatch layer only. +You MUST use explicit allowlists for worker selection and tool access. +You MUST keep worker results task-bounded, typed, and brief. +You SHOULD use handoffs instead of nested worker spawning when a platform supports handoffs. +You SHOULD treat undocumented nested delegation as unsupported for portable APS authoring. +You MUST treat Claude Code workers as leaf workers. +You SHOULD treat VS Code Copilot and OpenCode workers as leaf workers for portable APS authoring. + + + +GUIDE_VERSION: "1.0.0" + +PLATFORM_CAPABILITY_MATRIX: CSV<< +platform,coordinator_role,worker_role,documented_depth_policy,invocation_surface,notes +claude-code,main-thread agent only,markdown subagent,depth-1-only,Agent,"Workers cannot spawn workers." +vscode-copilot,main chat agent or prompt,subagent or custom agent worker,portable-depth-1,agent/runSubagent,"Custom-agent subagents are experimental and nested delegation is not documented." +opencode,primary agent,mode=subagent worker,portable-depth-1,Task,"Primary/subagent roles are documented and nested delegation is not documented." +generic,host-defined or manual APS coordinator,host-defined or external worker,host-defined,host-defined,"Use explicit APS dispatch processes when host behavior is unclear." +>> + +REQUEST_INTERFACE_RULES: TEXT<< +1. The worker block is the public interface into the worker. +2. The caller dispatch process MUST accept the same fields, names, and meanings. +3. If a platform needs renamed fields, keep the rename in the dispatch layer only. +4. Do not hide required worker inputs inside free-form prompt text. +5. Keep request types stable across platforms. +>> + +RESPONSE_INTERFACE_RULES: TEXT<< +1. The worker MUST return a typed result that matches a contract. +2. The caller MUST capture the worker result before the next step starts. +3. Keep summaries brief and task-bounded. +4. Do not leak platform-only metadata unless the caller explicitly asks for it. +>> + +PORTABLE_PATTERNS: JSON<< +{ + "coordinator_worker": { + "description": "One coordinator dispatches one worker and integrates the worker result.", + "best_for": ["single specialty task", "strong contract boundaries"] + }, + "fan_out_review": { + "description": "One coordinator dispatches multiple leaf workers in parallel and then compares typed results.", + "best_for": ["research", "review", "verification"] + }, + "sequential_handoff": { + "description": "One worker finishes, returns a typed result, and the coordinator hands off the next step to a different worker.", + "best_for": ["plan -> implement", "implement -> review"] + } +} +>> + +ANTI_PATTERNS: TEXT<< +- Worker-to-worker recursion without a documented host contract. +- Free-form worker prompts with hidden required fields. +- Caller processes that rename or reshape worker inputs in multiple places. +- Worker outputs that mix summary text, hidden state, and untyped data. +- Broad tool access for narrow workers. +>> + +APS_INTERFACE_EXAMPLE: TEXT<< +Worker contract: + +TICKET_ID: String +TARGET_PATHS: String[] + + +Caller dispatch process: + +USE `Agent` where: description="Review the requested files", prompt="Review the requested files", worker="reviewer" +SET WORKER_REQUEST := { TICKET_ID: TICKET_ID, TARGET_PATHS: TARGET_PATHS } +CAPTURE REVIEW_RESULT from `reviewer` +RETURN: REVIEW_RESULT + + +Rule: +- The caller args are the same interface as the worker input. +- The caller is responsible for the platform-specific call surface. +- The worker returns a typed result that the caller captures. +>> + +BIDIRECTIONAL_CONTRACT_RULE: TEXT<< +Request flow: caller process args -> worker . +Response flow: worker result -> caller capture variables. +The contract is bidirectional only when the caller defines both mappings explicitly. +>> + + + + +# Subagent Architecture Spec: + +## Coordinator +- Role: +- Dispatch surface: +- Depth policy: + +## Workers +| Worker | Role | Input contract | Output contract | Allowed tools | Notes | +|--------|------|----------------|-----------------|---------------|-------| +| | | | | | | + +## Request and response mapping + + +## Failure policy + + +WHERE: +- is String; comma-separated logical or host tool ids allowed for the worker. +- is String; descriptive name for the coordinator/worker design. +- is String; the coordinator responsibility statement. +- is String; one of depth-1-only, portable-depth-1, host-defined. +- is String; host invocation surface such as Agent, agent/runSubagent, Task, or manual APS process. +- is Markdown; what the coordinator does when a worker fails, times out, or returns invalid data. +- is String; id or label of the worker request contract. +- is String; id or label of the worker response contract. +- is Markdown; explicit mapping from caller args to worker input and from worker result to caller capture. +- is String; worker identifier. +- is String; short notes about visibility, allowlists, or platform limits. +- is String; worker responsibility statement. + + + +# Subagent Contract Checklist + +- [ ] The coordinator is the single dispatch owner. +- [ ] Each worker has an explicit APS contract. +- [ ] Each caller dispatch process mirrors the worker input fields one-for-one. +- [ ] Each worker returns a typed result. +- [ ] The caller captures the worker result before the next step starts. +- [ ] Nested delegation is either documented by the host or avoided. +- [ ] Worker tool access uses least privilege. +- [ ] Worker visibility and allowlists are explicit. +- [ ] Platform-only routing details stay outside the portable contract. + +WHERE: +- This checklist is a fixed review format with no placeholders. + + diff --git a/.github/skills/agnostic-prompt-standard/platforms/README.md b/.github/skills/agnostic-prompt-standard/platforms/README.md index ea6173a..e4aeac7 100644 --- a/.github/skills/agnostic-prompt-standard/platforms/README.md +++ b/.github/skills/agnostic-prompt-standard/platforms/README.md @@ -2,10 +2,11 @@ APS is designed to be **platform-agnostic**, but real hosts (IDEs, agent runtimes, CI bots) differ in: -- File discovery conventions (where prompts/agents/skills live) -- YAML frontmatter dialects (which fields exist, required/optional) +- File discovery conventions (where prompts, agents, and skills live) +- YAML frontmatter dialects (which fields exist and which are optional) - Tool availability, naming, and approval UX - Safety constraints (auto-approve settings, restricted file paths) +- Multi-agent orchestration surfaces (how a coordinator invokes workers) This folder contains **platform adapters** that describe those differences *without changing the APS v1.0 spec*. @@ -23,28 +24,50 @@ platforms/ templates/ # optional installable agent files .claude/agents/ # (claude-code) or .github/agents/ # (vscode-copilot) + # no templates/ # (generic / external tools) ``` The `adaptor.md` file contains three APS sections: 1. `` — platform-specific generation instructions -2. `` — all metadata: platform ID, detection markers, file conventions, tool registries, agent versioning +2. `` — metadata such as platform ID, detection markers, file conventions, subagent depth policy, and tool registries 3. `` — frontmatter and output format contracts +The `generic/` adapter is the neutral option for tool-agnostic or external-tool-only workflows. +It has no detection markers and no installable templates. + +## Subagent authoring contract + +Adapters should document the host-specific orchestration surface for coordinator and worker authoring. +At minimum, an adapter should state: + +- which artifact type is the coordinator +- which artifact type is the worker +- which tool or surface invokes the worker +- the documented depth policy +- how APS worker `` maps to caller dispatch args +- how worker outputs are captured back into the caller + +If nested delegation is undocumented, the adapter should default to **portable depth-1 authoring**. +That means one coordinator dispatches leaf workers, and all platform-specific routing stays in the caller dispatch layer. + +→ See [`guides/subagent-architecture-v1.0.0.guide.md`](../guides/subagent-architecture-v1.0.0.guide.md) + ## Add a new platform adapter 1. Copy `platforms/_template/` to `platforms//` 2. Fill in `adaptor.md` with platform-specific constants and formats -3. Optionally add a `templates/` directory with installable agent files -4. Do **not** change `references/` unless you are intentionally publishing an APS spec revision +3. Document coordinator/worker roles, dispatch surface, and depth policy +4. Optionally add a `templates/` directory with installable agent files +5. Do **not** change `references/` unless you are intentionally publishing an APS spec revision ## Contract - Anything under `references/` is **normative** APS. -- Anything under `platforms/` is **non-normative** (documentation/templates/mappings only). +- Anything under `platforms/` is **non-normative** (documentation, templates, and mappings only). - Adapters should prefer **mapping + configuration** over rewriting APS core rules. -## Scope and Philosophy +## Scope and philosophy Adapters are intended to **map** the APS standard to a host platform. They are **not** project generators. We do not provide generic project scaffolding (like `settings.json` or root `CLAUDE.md` templates). diff --git a/.github/skills/agnostic-prompt-standard/platforms/_template/adaptor.md b/.github/skills/agnostic-prompt-standard/platforms/_template/adaptor.md index 9e79355..050c580 100644 --- a/.github/skills/agnostic-prompt-standard/platforms/_template/adaptor.md +++ b/.github/skills/agnostic-prompt-standard/platforms/_template/adaptor.md @@ -1,20 +1,38 @@ Replace this section with platform-specific generation instructions. -Describe tool naming conventions, file locations, and frontmatter rules. +Describe tool naming conventions, file locations, frontmatter rules, and MCP config surfaces when applicable. +Document how a coordinator invokes workers on this host. +Map each worker APS `` field to the caller dispatch args. +If nested delegation is undocumented, default to portable depth-1 authoring. PLATFORM_ID: "your-platform-id" DISPLAY_NAME: "Your Platform" -ADAPTER_VERSION: "0.1.0" +ADAPTER_VERSION: "0.2.0" LAST_UPDATED: "YYYY-MM-DD" -INSTRUCTION_FILE_PATHS: [".github/copilot-instructions.md"] +SUBAGENT_AUTHORING_GUIDE: "guides/subagent-architecture-v1.0.0.guide.md" + +SUBAGENT_ARCHITECTURE: JSON<< +{ + "coordinator_role": "Describe the coordinator artifact or surface.", + "worker_role": "Describe the worker artifact or surface.", + "depth_policy": "host-defined-or-portable-depth-1", + "documented_limit": "Describe documented nesting limits or say not documented.", + "invocation_surface": "Describe the tool, command, handoff, or API that invokes the worker.", + "request_contract_rule": "Worker is the public request interface and the caller mirrors it in dispatch args.", + "response_contract_rule": "Worker returns a typed result and the caller captures it before the next step.", + "portability_rule": "Keep host-specific routing in the caller dispatch layer only." +} +>> +INSTRUCTION_FILE_PATHS: [".github/copilot-instructions.md"] DETECTION_MARKERS: [".github/agents/", "path/to/marker.file"] +MCP_CONFIG_PATHS: [] DOCS_HOME_URL: "https://example.com/docs" - \ No newline at end of file + diff --git a/.github/skills/agnostic-prompt-standard/platforms/claude-code/adaptor.md b/.github/skills/agnostic-prompt-standard/platforms/claude-code/adaptor.md index b6b2343..3024c39 100644 --- a/.github/skills/agnostic-prompt-standard/platforms/claude-code/adaptor.md +++ b/.github/skills/agnostic-prompt-standard/platforms/claude-code/adaptor.md @@ -7,30 +7,70 @@ Rules are stored in .claude/rules/*.md with optional path-scoped YAML frontmatte File imports use @path syntax (e.g., @README.md, @docs/guide.md, @~/.claude/shared-rules.md). Hooks execute shell commands at lifecycle events and are configured in .claude/settings.json. Permissions use Tool(specifier) with allow/deny/ask arrays in .claude/settings.json. +Claude Code stores project-scoped MCP servers in .mcp.json at the project root and user/local MCP servers in ~/.claude.json. Tools in frontmatter are comma-separated strings (e.g., tools: Read, Write, Edit). +You MUST load `guides/subagent-architecture-v1.0.0.guide.md` before authoring coordinator or worker agents. +You MUST treat `.claude/agents/*.md` worker agents as leaf workers because Claude subagents cannot spawn subagents. +You MUST map worker APS `` fields to caller dispatch process args one-for-one. PLATFORM_ID: "claude-code" DISPLAY_NAME: "Claude Code CLI" -ADAPTER_VERSION: "2.0.0" -LAST_UPDATED: "2026-02-19" +ADAPTER_VERSION: "2.1.0" +LAST_UPDATED: "2026-03-12" + +ARTIFACT_TYPES: CSV<< +type,file_pattern,config_format +agent,.claude/agents/*.md,CC_AGENT_FRONTMATTER_V1 +rules,.claude/rules/*.md,CC_RULES_FRONTMATTER_V1 +hooks,.claude/settings.json,CC_HOOKS_CONFIG_V1 +permissions,.claude/settings.json,CC_PERMISSIONS_CONFIG_V1 +>> + +SUBAGENT_AUTHORING_GUIDE: "guides/subagent-architecture-v1.0.0.guide.md" + +SUBAGENT_ARCHITECTURE: JSON<< +{ + "coordinator_role": "Main-thread agent only", + "worker_role": "Markdown-defined subagent in .claude/agents/*.md", + "depth_policy": "depth-1-only", + "documented_limit": "Subagents cannot spawn other subagents.", + "invocation_tool": "Agent", + "invocation_aliases": ["Task"], + "allowlist_surface": "tools: Agent(worker, reviewer)", + "definition_paths": ["./.claude/agents/*.md", "~/.claude/agents/*.md"], + "defaults": { + "model": "inherit when omitted", + "tools": "inherit all tools when omitted", + "skills": "do not inherit; list explicitly", + "permissionMode": "inherits current permission context unless overridden" + }, + "request_contract_rule": "Author each worker as the public request interface and mirror it in the caller dispatch process args.", + "response_contract_rule": "Return a typed result and capture it in the caller before the next step.", + "portability_rule": "Author Claude workers as leaf workers. Keep all platform-specific Agent wiring in the caller dispatch layer." +} +>> INSTRUCTION_FILE_PATHS: ["./CLAUDE.md", "./.claude/CLAUDE.md", "./.claude/rules/*.md", "./CLAUDE.local.md", "~/.claude/CLAUDE.md", "~/.claude/rules/*.md"] AGENT_FILE_PATHS: ["./.claude/agents/*.md", "~/.claude/agents/*.md"] -MCP_CONFIG_PATHS: ["./.mcp.json"] +MCP_CONFIG_PATHS: ["./.mcp.json", "~/.claude.json"] SETTINGS_FILE_PATHS: ["./.claude/settings.json", "./.claude/settings.local.json", "~/.claude/settings.json"] MEMORY_LOAD_ORDER: [INSTRUCTION_FILE_PATHS, AGENT_FILE_PATHS, MCP_CONFIG_PATHS, SETTINGS_FILE_PATHS] DETECTION_MARKERS: [".claude", "CLAUDE.md", "CLAUDE.local.md", ".mcp.json", ".claude/settings.json", ".claude/agents", ".claude/rules"] +CONFIG_SCOPES: ["managed", "user", "project", "local"] +SUBAGENT_MEMORY_SCOPES: ["user", "project", "local"] +SUBAGENT_RUN_MODES: ["foreground", "background"] + MEMORY_LEVEL_ENTERPRISE: "Managed by organization admins." MEMORY_LEVEL_PROJECT: ["./CLAUDE.md", "./.claude/CLAUDE.md"] MEMORY_LEVEL_RULES: ["./.claude/rules/*.md"] MEMORY_LEVEL_USER: ["~/.claude/CLAUDE.md", "./CLAUDE.local.md"] MEMORY_OVERRIDE_ORDER: [MEMORY_LEVEL_ENTERPRISE, MEMORY_LEVEL_PROJECT, MEMORY_LEVEL_RULES, MEMORY_LEVEL_USER] -HOOK_EVENTS: ["PreToolUse", "PostToolUse", "PermissionRequest", "Stop", "SubagentStop", "UserPromptSubmit", "SessionStart", "SessionEnd", "PreCompact", "Notification"] +HOOK_EVENTS: ["PreToolUse", "PostToolUse", "PermissionRequest", "Stop", "SubagentStart", "SubagentStop", "UserPromptSubmit", "SessionStart", "SessionEnd", "PreCompact", "Notification"] HOOK_CONFIG_PATH: ".claude/settings.json" TOOL_NAMING_STYLE: "PascalCase" @@ -40,33 +80,34 @@ TOOL_FRONTMATTER_SYNTAX: "comma-separated strings (e.g., tools: Read, Write, Edi TOOLS: CSV<< name,toolset,risk,side_effects,description,params -Read,filesystem,low,reads,"Read file contents. Supports text/images/PDFs/notebooks.","[file_path:string:required, offset:integer:optional, limit:integer:optional, pages:string:optional]" -Write,filesystem,medium,writes,"Create or overwrite files. Read first if exists. Prefer Edit.","[file_path:string:required, content:string:required]" -Edit,filesystem,medium,writes,"Exact string replacement. old_string must be unique.","[file_path:string:required, old_string:string:required, new_string:string:required, replace_all:boolean:optional]" -Glob,filesystem,low,reads,"Find files by glob pattern. Returns paths sorted by modification time.","[pattern:string:required, path:string:optional]" -Grep,filesystem,low,reads,"Search file contents using regex (ripgrep). Use glob/type for filtering.","[pattern:string:required, path:string:optional, glob:string:optional, type:string:optional, output_mode:enum(content|files_with_matches|count):optional]" -NotebookEdit,filesystem,medium,writes,"Replace/insert/delete cells in Jupyter notebooks.","[notebook_path:string:required, new_source:string:required, cell_id:string:optional, cell_type:enum(code|markdown):optional, edit_mode:enum(replace|insert|delete):optional]" -Bash,execution,high,executes,"Execute bash commands. Use for git/npm/docker. Avoid for file ops.","[command:string:required, description:string:optional, timeout:integer:optional, run_in_background:boolean:optional]" -Task,execution,medium,mixed,"Launch specialized subagents for complex multi-step tasks.","[description:string:required, prompt:string:required, subagent_type:string:required, model:enum(sonnet|opus|haiku):optional, run_in_background:boolean:optional, max_turns:integer:optional]" -TaskOutput,execution,low,reads,"Retrieve output from running or completed background task.","[task_id:string:required, block:boolean:optional, timeout:integer:optional]" +Read,filesystem,low,reads,"Read file contents. Supports text, images, PDFs, and notebooks.","[file_path:string:required, offset:integer:optional, limit:integer:optional, pages:string:optional]" +Write,filesystem,medium,writes,"Create or overwrite files. Read first if the file exists. Prefer Edit for localized changes.","[file_path:string:required, content:string:required]" +Edit,filesystem,medium,writes,"Exact string replacement. old_string must be unique unless replace_all is true.","[file_path:string:required, old_string:string:required, new_string:string:required, replace_all:boolean:optional]" +Glob,filesystem,low,reads,"Find files by glob pattern.","[pattern:string:required, path:string:optional]" +Grep,filesystem,low,reads,"Search file contents using regex.","[pattern:string:required, path:string:optional, glob:string:optional, type:string:optional, output_mode:enum(content|files_with_matches|count):optional]" +NotebookEdit,filesystem,medium,writes,"Replace, insert, or delete notebook cells.","[notebook_path:string:required, new_source:string:required, cell_id:string:optional, cell_type:enum(code|markdown):optional, edit_mode:enum(replace|insert|delete):optional]" +Bash,execution,high,executes,"Execute bash commands. Use for git, npm, docker, and test runs.","[command:string:required, description:string:optional, timeout:integer:optional, run_in_background:boolean:optional]" +Agent,execution,medium,mixed,"Launch specialized subagents from a main-thread agent.","[description:string:required, prompt:string:required, subagent_type:string:required, model:enum(sonnet|opus|haiku|inherit):optional, run_in_background:boolean:optional, max_turns:integer:optional]" +Task,execution,medium,mixed,"Deprecated alias for Agent.","[description:string:required, prompt:string:required, subagent_type:string:required, model:enum(sonnet|opus|haiku|inherit):optional, run_in_background:boolean:optional, max_turns:integer:optional]" +TaskOutput,execution,low,reads,"Retrieve output from a running or completed background task.","[task_id:string:required, block:boolean:optional, timeout:integer:optional]" TaskStop,execution,low,executes,"Stop a running background task by ID.","[task_id:string:required]" TaskCreate,execution,low,none,"Create a new task in the structured task list.","[subject:string:required, description:string:required, activeForm:string:optional]" -TaskUpdate,execution,low,none,"Update task status/details/dependencies.","[taskId:string:required, status:enum(pending|in_progress|completed|deleted):optional, subject:string:optional, description:string:optional]" -TaskList,execution,low,reads,"List all tasks with status and dependencies.","" -TaskGet,execution,low,reads,"Get full details of a specific task by ID.","[taskId:string:required]" -TodoWrite,execution,low,none,"Create and manage structured task/todo items for tracking session progress.","[subject:string:required, description:string:required, activeForm:string:optional]" -MCPSearch,execution,low,reads,"Search for and load MCP tools. Requires MCP servers configured.","" -WebFetch,web,medium,network,"Fetch URL content and process with prompt. 15-min cache. Fails for auth URLs.","[url:string:required, prompt:string:required]" -WebSearch,web,medium,network,"Search the web. Must include Sources section with URLs.","[query:string:required, allowed_domains:array:optional, blocked_domains:array:optional]" -AskUserQuestion,interaction,low,none,"Ask user questions. 1-4 questions with 2-4 options each.","[questions:array:required]" -Skill,skills,medium,mixed,"Execute a skill (slash command) within the conversation.","[skill:string:required, args:string:optional]" -EnterPlanMode,planning,low,none,"Transition to plan mode for implementation approaches.","" -ExitPlanMode,planning,low,none,"Signal plan completion and request user approval.","[allowedPrompts:array:optional, pushToRemote:boolean:optional]" -LSP,code_intelligence,low,reads,"Code intelligence via Language Server Protocol. IDE-only.","" +TaskUpdate,execution,low,none,"Update task status, details, or dependencies.","[taskId:string:required, status:enum(pending|in_progress|completed|deleted):optional, subject:string:optional, description:string:optional]" +TaskList,execution,low,reads,"List all structured tasks.","" +TaskGet,execution,low,reads,"Get full details for a structured task.","[taskId:string:required]" +TodoWrite,execution,low,none,"Create and manage structured todo items for session progress.","[subject:string:required, description:string:required, activeForm:string:optional]" +MCPSearch,execution,low,reads,"Search for and load MCP tools.","" +WebFetch,web,medium,network,"Fetch URL content and process it with a prompt.","[url:string:required, prompt:string:required]" +WebSearch,web,medium,network,"Search the web.","[query:string:required, allowed_domains:array:optional, blocked_domains:array:optional]" +AskUserQuestion,interaction,low,none,"Ask the user structured questions.","[questions:array:required]" +Skill,skills,medium,mixed,"Execute a skill within the conversation.","[skill:string:required, args:string:optional]" +EnterPlanMode,planning,low,none,"Transition to plan mode.","" +ExitPlanMode,planning,low,none,"Signal plan completion and request approval.","[allowedPrompts:array:optional, pushToRemote:boolean:optional]" +LSP,code_intelligence,low,reads,"Code intelligence via Language Server Protocol.","" >> -RECOMMENDED_PLANNER_TOOLS: ["Read", "Glob", "Grep", "WebFetch", "WebSearch", "TaskCreate", "TaskUpdate", "TaskList", "TaskGet", "AskUserQuestion", "Task"] -RECOMMENDED_IMPLEMENTER_TOOLS: ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "TaskCreate", "TaskUpdate", "TaskList", "TaskGet", "Task", "NotebookEdit"] +RECOMMENDED_PLANNER_TOOLS: ["Read", "Glob", "Grep", "WebFetch", "WebSearch", "TaskCreate", "TaskUpdate", "TaskList", "TaskGet", "AskUserQuestion", "Agent"] +RECOMMENDED_IMPLEMENTER_TOOLS: ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "TaskCreate", "TaskUpdate", "TaskList", "TaskGet", "Agent", "NotebookEdit"] PERMISSION_MODES: ["default", "acceptEdits", "dontAsk", "bypassPermissions", "plan"] AGENT_MODELS: ["sonnet", "opus", "haiku", "inherit"] @@ -76,7 +117,7 @@ AGENT_VERSIONING: JSON<< "templates": [ { "path": "templates/.claude/agents/aps-v{major}.{minor}.{patch}.md", - "current_path": "templates/.claude/agents/aps-v1.1.16.md", + "current_path": "templates/.claude/agents/aps-v1.2.1.md", "frontmatter": { "name_pattern": "aps-v{major}-{minor}-{patch}", "description_pattern": "Generate APS v{major}.{minor}.{patch} agent files for any platform: load APS skill + target platform adapter, extract intent, then generate+write+lint." @@ -94,24 +135,30 @@ SKILL_AUTHORING_RESOURCES: JSON<< } >> -DOCS_MEMORY_URL: "https://docs.anthropic.com/en/docs/claude-code/memory" -DOCS_SETTINGS_URL: "https://docs.anthropic.com/en/docs/claude-code/settings" -DOCS_HOOKS_URL: "https://docs.anthropic.com/en/docs/claude-code/hooks" -DOCS_MCP_URL: "https://docs.anthropic.com/en/docs/claude-code/mcp" -DOCS_TOOLS_URL: "https://docs.anthropic.com/en/docs/claude-code/cli-reference" -DOCS_SUBAGENTS_URL: "https://docs.anthropic.com/en/docs/claude-code/sub-agents" +DOCS_MEMORY_URL: "https://code.claude.com/docs/en/memory" +DOCS_SETTINGS_URL: "https://code.claude.com/docs/en/settings" +DOCS_HOOKS_URL: "https://code.claude.com/docs/en/hooks" +DOCS_MCP_URL: "https://code.claude.com/docs/en/mcp" +DOCS_TOOLS_URL: "https://code.claude.com/docs/en/cli-reference" +DOCS_SUBAGENTS_URL: "https://code.claude.com/docs/en/sub-agents" - + --- name: description: "" -model: tools: disallowedTools: +model: permissionMode: -skills: +maxTurns: +skills: + - +mcpServers: + - +memory: +background: hooks: : - matcher: "" @@ -121,16 +168,20 @@ hooks: --- WHERE: -- is String; regex: ^[a-z][a-z0-9-]{1,63}$; unique across all loaded subagents. -- is String; describes what the subagent does and when to invoke it. -- is one of AGENT_MODELS; default inherit; omit to use default. -- is String; comma-separated names from TOOLS; omit if no allowlist needed. -- is String; comma-separated names from TOOLS; omit if no denylist needed. -- is one of PERMISSION_MODES; default default; omit to use default. -- is String; comma-separated skill names; omit if no skills needed. -- is one of: "PreToolUse", "PostToolUse", "Stop"; subset of HOOK_EVENTS. -- is String; tool name to match (e.g., "Bash", "Write"). +- is String; single-line double-quoted string that says what the agent does and when to invoke it. +- is String; regex: ^[a-z][a-z0-9-]{1,63}$; unique across all loaded agents. +- is Boolean; true to always run the worker as a background task. +- is String; comma-separated names from TOOLS; omit if no denylist is needed. - is String; shell command to execute; receives tool context via environment variables. +- is one of HOOK_EVENTS. +- is String; tool name or regex pattern to match. +- is Integer; maximum number of agentic turns before the agent stops. +- is String; preconfigured MCP server name; repeat or replace the list with inline server objects when needed. +- is one of SUBAGENT_MEMORY_SCOPES; omit if no persistent memory is needed. +- is one of AGENT_MODELS; omit to inherit the parent model. +- is one of PERMISSION_MODES; omit to inherit the current permission context. +- is String; skill id to preload into the agent context; omit the list if no skills are needed. +- is String; comma-separated PascalCase names from TOOLS. For main-thread coordinators use `Agent` or `Agent(worker, reviewer)`. For leaf workers omit `Agent`. @@ -140,7 +191,7 @@ paths: --- WHERE: -- is String; standard glob syntax (e.g., "src/**/*.ts", "**/*.test.ts", "docs/**/*.md"); ** for recursive matching, * for single directory. +- is String; standard glob syntax such as "src/**/*.ts", "**/*.test.ts", or "docs/**/*.md". @@ -157,7 +208,7 @@ WHERE: WHERE: - is one of HOOK_EVENTS. -- is String; tool name to match (e.g., "Bash"); omit matcher for unconditional hooks. +- is String; tool or agent matcher; omit matcher for unconditional hooks. - is String; shell command to execute at the lifecycle event. @@ -171,7 +222,7 @@ WHERE: } WHERE: -- is String; exact tool name from TOOLS (e.g., "Read", "Glob", "Grep"). -- is String; tool name with optional argument restriction (e.g., "Bash(rm -rf *)"). +- is String; exact PascalCase tool name from TOOLS, for example "Read", "Glob", "Grep", or "Agent(worker)". +- is String; tool name with optional argument restriction, for example "Bash(rm -rf *)" or "Agent(my-custom-agent)". diff --git a/.github/skills/agnostic-prompt-standard/platforms/claude-code/templates/.claude/agents/aps-v1.1.16.md b/.github/skills/agnostic-prompt-standard/platforms/claude-code/templates/.claude/agents/aps-v1.2.1.md similarity index 98% rename from .github/skills/agnostic-prompt-standard/platforms/claude-code/templates/.claude/agents/aps-v1.1.16.md rename to .github/skills/agnostic-prompt-standard/platforms/claude-code/templates/.claude/agents/aps-v1.2.1.md index 42d1932..ad5021f 100644 --- a/.github/skills/agnostic-prompt-standard/platforms/claude-code/templates/.claude/agents/aps-v1.1.16.md +++ b/.github/skills/agnostic-prompt-standard/platforms/claude-code/templates/.claude/agents/aps-v1.2.1.md @@ -1,6 +1,6 @@ --- -name: aps-v1-1-16 -description: "Generate APS v1.1.16 agent files for any platform: load APS skill + target platform adapter, extract intent, then generate+write+lint. Author: Christopher Buckley. Co-authors: Juan Burckhardt, Anastasiya Smirnova. URL: https://github.com/chris-buckley/agnostic-prompt-standard" +name: aps-v1-2-1 +description: "Generate APS v1.2.1 agent files for any platform: load APS skill + target platform adapter, extract intent, then generate+write+lint. Author: Christopher Buckley. Co-authors: Juan Burckhardt, Anastasiya Smirnova. URL: https://github.com/chris-buckley/agnostic-prompt-standard" model: inherit tools: Read, Write, Glob, Grep, Bash, TodoWrite disallowedTools: Edit, MultiEdit diff --git a/.github/skills/agnostic-prompt-standard/platforms/generic/adaptor.md b/.github/skills/agnostic-prompt-standard/platforms/generic/adaptor.md new file mode 100644 index 0000000..5a07e21 --- /dev/null +++ b/.github/skills/agnostic-prompt-standard/platforms/generic/adaptor.md @@ -0,0 +1,63 @@ + +Generate artifacts for tool-agnostic APS usage or for runtimes that use external tools only. +You MUST load `guides/subagent-architecture-v1.0.0.guide.md` before authoring coordinator or worker contracts. +You MUST keep the APS coordinator as the single dispatch owner unless the host documents nested delegation. +You MUST define worker `` as the interface into the worker and mirror it in the caller dispatch process. +You MUST define worker `` outputs and capture them in the caller before the next step. +You MUST isolate host-specific tool or routing names in config files instead of APS process text. +Use this adapter when a host has no stable native tool registry, when tools come only from MCP or an equivalent external declaration file, or when you want one neutral tool layer across hosts. +Do not assume host-specific file names, frontmatter, or native tool naming. +Declare external tools in `predefinedTools.json` with canonical APS tool ids. +If a host exposes decorated runtime names, map them with `config.json` ALIAS entries instead of duplicating tool objects. + + + +PLATFORM_ID: "generic" +DISPLAY_NAME: "Generic / External Tools" +ADAPTER_VERSION: "1.1.0" +LAST_UPDATED: "2026-03-12" + +SUBAGENT_AUTHORING_GUIDE: "guides/subagent-architecture-v1.0.0.guide.md" + +SUBAGENT_ARCHITECTURE: JSON<< +{ + "coordinator_role": "Host-defined or manual APS coordinator", + "worker_role": "Host-defined, external, or user-mediated worker", + "depth_policy": "unknown-use-depth-1-by-default", + "invocation_surface": "host-defined", + "request_contract_rule": "Define the worker as the public interface and mirror it in the caller dispatch process args.", + "response_contract_rule": "Define a typed worker result and capture it before the caller continues.", + "fallback_pattern": "If the host has no native subagent surface, model delegation as explicit APS processes or user-mediated steps." +} +>> + +INSTRUCTION_FILE_PATHS: [] +DETECTION_MARKERS: [] +MCP_CONFIG_PATHS: [] +TOOL_SOURCES: ["native", "mcp", "mixed", "none"] +HOST_CAPABILITY_STATES: ["unknown", "depth-1", "nested", "manual"] +EXTERNAL_TOOL_DECLARATION_FILES: ["predefinedTools.json", "config.json"] + +DOCS_MCP_URL: "https://modelcontextprotocol.io/specification/2025-06-18/schema" + + + + +# Generic Coordinator Worker Map + +| Worker | Input contract | Invocation surface | Output contract | Notes | +|--------|----------------|--------------------|-----------------|-------| +| | | | | | + +## Caller mapping + + +WHERE: +- is String; worker request contract id or label. +- is String; host-defined invocation mechanism or `manual APS process`. +- is String; routing, policy, or fallback notes. +- is String; worker response contract id or label. +- is Markdown; explicit mapping from caller args to worker input and from worker output to caller capture. +- is String; worker identifier. + + diff --git a/.github/skills/agnostic-prompt-standard/platforms/opencode/adaptor.md b/.github/skills/agnostic-prompt-standard/platforms/opencode/adaptor.md index 938c33a..79eb2e2 100644 --- a/.github/skills/agnostic-prompt-standard/platforms/opencode/adaptor.md +++ b/.github/skills/agnostic-prompt-standard/platforms/opencode/adaptor.md @@ -1,23 +1,159 @@ -Generate artifacts for the OpenCode agent runtime using the constants in this adapter. -OpenCode uses AGENTS.md and JSONC configuration files. -Configuration supports JSON with comments (JSONC). +Generate artifacts for the OpenCode agent runtime using the constants and format contracts in this adapter. +You MUST load `guides/subagent-architecture-v1.0.0.guide.md` before authoring primary agents or subagents. +You MUST treat `mode: primary` agents as coordinators and `mode: subagent` agents as workers. +You SHOULD treat OpenCode workers as leaf workers for portable APS authoring because nested delegation is not documented. +You MUST map worker APS `` fields to caller dispatch process args one-for-one. +You MUST keep host-specific `Task` and command `subtask` wiring in the caller dispatch layer. PLATFORM_ID: "opencode" DISPLAY_NAME: "OpenCode" -ADAPTER_VERSION: "2.0.0" -LAST_UPDATED: "2026-02-19" +ADAPTER_VERSION: "2.1.0" +LAST_UPDATED: "2026-03-12" + +ARTIFACT_TYPES: CSV<< +type,scope,file_pattern,config_format +agent,project,.opencode/agents/*.md,OPENCODE_AGENT_FRONTMATTER_V1 +agent,user,~/.config/opencode/agents/*.md,OPENCODE_AGENT_FRONTMATTER_V1 +config,project,.opencode/opencode.json,OPENCODE_AGENT_CONFIG_JSON_V1 +config,project,.opencode/opencode.jsonc,OPENCODE_AGENT_CONFIG_JSON_V1 +config,project,opencode.json,OPENCODE_AGENT_CONFIG_JSON_V1 +config,project,opencode.jsonc,OPENCODE_AGENT_CONFIG_JSON_V1 +>> + +SUBAGENT_AUTHORING_GUIDE: "guides/subagent-architecture-v1.0.0.guide.md" + +SUBAGENT_ARCHITECTURE: JSON<< +{ + "coordinator_role": "Primary agent", + "worker_role": "Subagent configured with mode: subagent", + "depth_policy": "portable-depth-1", + "documented_limit": "Primary and subagent roles are documented, but nested delegation is not documented.", + "invocation_tool": "Task", + "manual_invocation": "@mention", + "definition_paths": [".opencode/agents/*.md", "~/.config/opencode/agents/*.md"], + "allowlist_surface": "permission.task", + "visibility_surface": "hidden", + "mode_surface": "mode", + "defaults": { + "model": "subagent inherits the invoking primary model when omitted", + "todo_tools": "todoread and todowrite are disabled for subagents by default" + }, + "request_contract_rule": "Define the worker as the public request interface and mirror it in the caller dispatch process args.", + "response_contract_rule": "Return a typed or tightly bounded result and capture it in the primary process before the next step.", + "command_rule": "If a command targets a subagent it triggers a subagent invocation by default. Use subtask:true to force subagent invocation." +} +>> INSTRUCTION_FILE_PATHS: ["AGENTS.md", ".opencode/instructions.md"] -CONFIG_FILE_PATHS: [".opencode/opencode.jsonc", ".opencode/opencode.json", "opencode.json", "opencode.jsonc", ".opencode.json"] +AGENT_FILE_PATHS: [".opencode/agents/*.md", "~/.config/opencode/agents/*.md"] +CONFIG_FILE_PATHS: [".opencode/opencode.json", ".opencode/opencode.jsonc", "opencode.json", "opencode.jsonc", ".opencode.json"] +MCP_CONFIG_PATHS: [".opencode/opencode.json", ".opencode/opencode.jsonc", "opencode.json", "opencode.jsonc", ".opencode.json"] +DETECTION_MARKERS: [".opencode", ".opencode/agents", ".opencode/opencode.json", ".opencode/opencode.jsonc", "opencode.json", "opencode.jsonc", ".opencode.json"] -DETECTION_MARKERS: [".opencode", ".opencode/opencode.jsonc", ".opencode/opencode.json", "opencode.json", "opencode.jsonc", ".opencode.json"] +AGENT_MODES: ["primary", "subagent", "all"] +COMMAND_SUBTASK_RULE: "If a command sets agent to a subagent, it triggers subagent invocation by default. Use subtask:false to disable. Use subtask:true to force subagent invocation." +SUBAGENT_TODO_DEFAULT: "todoread and todowrite are disabled for subagents by default." DOCS_OFFICIAL_URL: "https://opencode.ai/docs" -DOCS_CONFIG_URL: "https://opencode.ai/docs/config" +DOCS_AGENTS_URL: "https://opencode.ai/docs/agents/" +DOCS_COMMANDS_URL: "https://opencode.ai/docs/commands/" +DOCS_PERMISSIONS_URL: "https://opencode.ai/docs/permissions/" +DOCS_TOOLS_URL: "https://opencode.ai/docs/tools/" +DOCS_MCP_URL: "https://opencode.ai/docs/mcp-servers/" + +--- +description: +mode: +model: +temperature: +steps: +tools: + : +permission: + : + task: + "": +hidden: +disable: +--- + +WHERE: +- is String; glob pattern matched against subagent names in permission.task. +- is String; required description of what the agent does and when to use it. +- is Boolean; true to disable the agent. +- is Boolean; only applicable to mode `subagent`; hides the worker from `@` autocomplete. +- is one of AGENT_MODES. +- is String; provider/model-id. Omit it on workers to inherit the invoking primary model. +- is String; permission key such as `edit`, `bash`, `webfetch`, `todoread`, or `todowrite`. +- is String; one of `allow`, `ask`, or `deny`. +- is Integer; maximum number of agentic steps; prefer `steps` over the deprecated `maxSteps`. +- is String; one of `allow`, `ask`, or `deny`. +- is Number; typical range 0.0 to 1.0. +- is Boolean; true or false. +- is String; tool id or wildcard such as `write`, `edit`, `bash`, or `mymcp_*`. +- The markdown filename becomes the agent name. + + + +{ + "agent": { + "": { + "description": "", + "mode": "", + "model": "", + "steps": , + "tools": { + "": + }, + "permission": { + "": "", + "task": { + "": "" + } + }, + "hidden": , + "disable": + } + } +} + +WHERE: +- is String; glob pattern matched against subagent names in permission.task. +- is String; agent id. +- is String; required description of what the agent does and when to use it. +- is Boolean; true to disable the agent. +- is Boolean; only applies to mode `subagent`. +- is one of AGENT_MODES. +- is String; provider/model-id. +- is String; permission key such as `edit`, `bash`, or `webfetch`. +- is String; one of `allow`, `ask`, or `deny`. +- is Integer; maximum number of agentic steps. +- is String; one of `allow`, `ask`, or `deny`. +- is Boolean; true or false. +- is String; tool id or wildcard pattern. + + + +{ + "command": { + "": { + "agent": "", + "subtask": , + "model": "" + } + } +} + +WHERE: +- is String; agent id that executes the command. +- is String; command id. +- is String; optional model override for the command execution. +- is Boolean; true to force subagent invocation and isolate context. + diff --git a/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/adaptor.md b/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/adaptor.md index c54a6ed..666e826 100644 --- a/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/adaptor.md +++ b/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/adaptor.md @@ -7,24 +7,66 @@ Agents are stored in .github/agents/*.agent.md with YAML frontmatter. Prompt files are stored in .github/prompts/*.prompt.md with YAML frontmatter. Instructions are in .github/copilot-instructions.md and .github/instructions/*.instructions.md. Skills are at .github/skills//SKILL.md. +Workspace MCP servers are configured in .vscode/mcp.json. Use toolSet name to include all tools in a set, or qualifiedName for individual tools. The functionName is resolved automatically at runtime. Generated frontmatter MUST NOT contain YAML comments. Description MUST be a single-line quoted string (avoid YAML block scalars). +You MUST load `guides/subagent-architecture-v1.0.0.guide.md` before authoring coordinator or worker agents. +You SHOULD treat custom-agent subagents as leaf workers for portable APS authoring because nested delegation is not documented. +You MUST map worker APS `` fields to caller dispatch process args one-for-one. PLATFORM_ID: "vscode-copilot" DISPLAY_NAME: "VS Code + GitHub Copilot" -ADAPTER_VERSION: "2.0.0" -LAST_UPDATED: "2026-02-19" +ADAPTER_VERSION: "2.1.0" +LAST_UPDATED: "2026-03-12" + +ARTIFACT_TYPES: CSV<< +type,scope,file_pattern,frontmatter_format +agent,project,.github/agents/*.agent.md,VSCODE_AGENT_FRONTMATTER_V1 +agent,project,.claude/agents/*.md,VSCODE_AGENT_FRONTMATTER_V1 +agent,user,~/.copilot/agents/*.agent.md,VSCODE_AGENT_FRONTMATTER_V1 +prompt,project,.github/prompts/*.prompt.md,VSCODE_PROMPT_FRONTMATTER_V1 +instructions,project,.github/copilot-instructions.md, +scoped-instructions,project,.github/instructions/*.instructions.md,VSCODE_INSTRUCTIONS_FRONTMATTER_V1 +skill,project,.github/skills//SKILL.md,VSCODE_SKILL_FRONTMATTER_V1 +skill,personal,~/.copilot/skills//SKILL.md,VSCODE_SKILL_FRONTMATTER_V1 +mcp-config,project,.vscode/mcp.json, +>> + +SUBAGENT_AUTHORING_GUIDE: "guides/subagent-architecture-v1.0.0.guide.md" + +SUBAGENT_ARCHITECTURE: JSON<< +{ + "coordinator_role": "Main chat agent or prompt that can call agent/runSubagent", + "worker_role": "Built-in subagent or custom .agent.md agent used as a subagent", + "depth_policy": "portable-depth-1", + "documented_limit": "Custom-agent subagents are experimental and nested delegation is not documented.", + "invocation_tools": ["agent", "runSubagent"], + "definition_paths": [".github/agents/*.agent.md", ".claude/agents/*.md", "~/.copilot/agents/*.agent.md"], + "default_inheritance": { + "agent": "inherits the main agent", + "model": "inherits the main session unless overridden", + "tools": "inherits the main session unless overridden" + }, + "controls": { + "subagent_allowlist": "agents", + "visible_in_picker": "user-invocable", + "subagent_disable": "disable-model-invocation", + "handoff_chain": "handoffs" + }, + "request_contract_rule": "Define the worker as the interface and mirror it in the caller dispatch process args.", + "response_contract_rule": "The worker returns a summary or typed result that the main agent incorporates before continuing.", + "portability_rule": "Keep coordinator-owned dispatch and leaf workers. Use handoffs for sequential flows." +} +>> -INSTRUCTION_FILE_PATHS: [".github/copilot-instructions.md", ".github/instructions/*.instructions.md"] -AGENT_FILE_PATHS: [".github/agents/*.agent.md"] -PROMPT_FILE_PATHS: [".github/prompts/*.prompt.md"] -SKILL_FILE_PATHS: [".github/skills//SKILL.md", "~/.copilot/skills//SKILL.md"] +AGENT_FILE_PATHS: [".github/agents/*.agent.md", ".claude/agents/*.md", "~/.copilot/agents/*.agent.md"] +DETECTION_MARKERS: [".github/copilot-instructions.md", ".github/agents", ".claude/agents", ".github/prompts", ".github/instructions", ".github/skills", ".vscode/mcp.json"] -DETECTION_MARKERS: [".github/copilot-instructions.md", ".github/agents", ".github/prompts", ".github/instructions", ".github/skills"] +MCP_CONFIG_PATHS: [".vscode/mcp.json"] TOOL_NAMING_STYLE: "three-tier: toolSet / qualifiedName / functionName" TOOL_NAMING_QUALIFICATION: "qualifiedName for individual tools, toolSet for all tools in a set" @@ -33,56 +75,56 @@ TOOL_FRONTMATTER_SYNTAX: "YAML array (no # prefix)" TOOLS: CSV<< name,toolset,qualified_name,function_name,mention,risk,side_effects,description -semantic_search,search,search/codebase,semantic_search,#codebase,low,reads,"Search workspace for relevant code or documentation." +semantic_search,search,search/codebase,semantic_search,#codebase,low,reads,"Search the workspace for relevant code or documentation." get_changed_files,search,search/changes,get_changed_files,#changes,low,reads,"Get git diffs of current file changes." -list_code_usages,search,search/usages,list_code_usages,#usages,low,reads,"List usages of a function/class/variable." +list_code_usages,search,search/usages,list_code_usages,#usages,low,reads,"List usages of a function, class, or variable." file_search,search,search/fileSearch,file_search,#fileSearch,low,reads,"Search for files by glob pattern." -grep_search,search,search/textSearch,grep_search,#textSearch,low,reads,"Fast text search with exact string or regex." +grep_search,search,search/textSearch,grep_search,#textSearch,low,reads,"Fast exact or regex text search." get_search_view_results,search,search/searchResults,get_search_view_results,#searchResults,low,reads,"Get results from the Search view." -read_file,read,read/readFile,read_file,#readFile,low,reads,"Read contents of a file (1-indexed line range)." +read_file,read,read/readFile,read_file,#readFile,low,reads,"Read contents of a file." get_errors,read,read/problems,get_errors,#problems,low,reads,"Get compile or lint errors." -terminal_last_command,read,read/terminalLastCommand,terminal_last_command,#terminalLastCommand,low,reads,"Get last command run in active terminal." -terminal_selection,read,read/terminalSelection,terminal_selection,#terminalSelection,low,reads,"Get current selection in active terminal." -copilot_getNotebookSummary,read,read/notebookSummary,copilot_getNotebookSummary,#notebookSummary,low,reads,"Get list of Notebook cells with metadata." -read_notebook_cell_output,read,read/notebookCellOutput,read_notebook_cell_output,#notebookCellOutput,low,reads,"Retrieve output for a notebook cell." -create_directory,edit,edit/createDirectory,create_directory,#createDirectory,medium,writes,"Create a new directory structure (like mkdir -p)." -create_file,edit,edit/createFile,create_file,#createFile,medium,writes,"Create a new file with specified content." -replace_string_in_file,edit,edit/editFiles,replace_string_in_file,#editFiles,high,writes,"Replace a unique string in an existing file." -multi_replace_string_in_file,edit,edit/multiEditFiles,multi_replace_string_in_file,#multiEditFiles,high,writes,"Apply multiple replacements in a single call." -edit_notebook_file,edit,edit/editNotebook,edit_notebook_file,#editNotebook,high,writes,"Edit an existing Notebook file." -create_new_jupyter_notebook,edit,edit/createNotebook,create_new_jupyter_notebook,#createNotebook,medium,writes,"Generate a new Jupyter Notebook." +terminal_last_command,read,read/terminalLastCommand,terminal_last_command,#terminalLastCommand,low,reads,"Get the last command run in the active terminal." +terminal_selection,read,read/terminalSelection,terminal_selection,#terminalSelection,low,reads,"Get the current terminal selection." +copilot_getNotebookSummary,read,read/notebookSummary,copilot_getNotebookSummary,#notebookSummary,low,reads,"Get notebook cells with metadata." +read_notebook_cell_output,read,read/notebookCellOutput,read_notebook_cell_output,#notebookCellOutput,low,reads,"Read notebook cell output." +create_directory,edit,edit/createDirectory,create_directory,#createDirectory,medium,writes,"Create a directory structure." +create_file,edit,edit/createFile,create_file,#createFile,medium,writes,"Create a new file with content." +replace_string_in_file,edit,edit/editFiles,replace_string_in_file,#editFiles,high,writes,"Replace a unique string in a file." +multi_replace_string_in_file,edit,edit/multiEditFiles,multi_replace_string_in_file,#multiEditFiles,high,writes,"Apply multiple replacements in one call." +edit_notebook_file,edit,edit/editNotebook,edit_notebook_file,#editNotebook,high,writes,"Edit an existing notebook file." +create_new_jupyter_notebook,edit,edit/createNotebook,create_new_jupyter_notebook,#createNotebook,medium,writes,"Create a new notebook." run_in_terminal,execute,execute/runInTerminal,run_in_terminal,#runInTerminal,high,executes,"Execute shell commands in a persistent terminal." -get_terminal_output,execute,execute/getTerminalOutput,get_terminal_output,#getTerminalOutput,low,reads,"Get output of a terminal command." +get_terminal_output,execute,execute/getTerminalOutput,get_terminal_output,#getTerminalOutput,low,reads,"Get terminal command output." run_task,execute,execute/runTask,run_task,#runTask,high,executes,"Run an existing VS Code task." -create_and_run_task,execute,execute/createAndRunTask,create_and_run_task,#createAndRunTask,high,executes,"Create and run a build/run/custom task." -get_task_output,execute,execute/getTaskOutput,get_task_output,#getTaskOutput,low,reads,"Get the output of a task." -run_notebook_cell,execute,execute/runNotebookCell,run_notebook_cell,#runNotebookCell,high,executes,"Run a code cell in a notebook." +create_and_run_task,execute,execute/createAndRunTask,create_and_run_task,#createAndRunTask,high,executes,"Create and run a task." +get_task_output,execute,execute/getTaskOutput,get_task_output,#getTaskOutput,low,reads,"Get task output." +run_notebook_cell,execute,execute/runNotebookCell,run_notebook_cell,#runNotebookCell,high,executes,"Run a notebook cell." test_failure,execute,execute/testFailure,test_failure,#testFailure,low,reads,"Include test failure information." fetch_webpage,web,web/fetch,fetch_webpage,#fetch,medium,network,"Fetch main content from web pages." github_repo,web,web/githubRepo,github_repo,#githubRepo,medium,network,"Search a GitHub repository for source code." run_vscode_command,vscode,vscode/runCommand,run_vscode_command,#runVscodeCommand,high,mixed,"Run a VS Code command." -vscode_searchExtensions_internal,vscode,vscode/extensions,vscode_searchExtensions_internal,#extensions,low,network,"Browse VS Code Extensions Marketplace." +vscode_searchExtensions_internal,vscode,vscode/extensions,vscode_searchExtensions_internal,#extensions,low,network,"Browse the VS Code Extensions Marketplace." install_extension,vscode,vscode/installExtension,install_extension,#installExtension,high,writes,"Install a VS Code extension." get_project_setup_info,vscode,vscode/getProjectSetupInfo,get_project_setup_info,#getProjectSetupInfo,low,none,"Get project setup info for scaffolding." open_simple_browser,vscode,vscode/openSimpleBrowser,open_simple_browser,#openSimpleBrowser,medium,none,"Preview a website in Simple Browser." -create_new_workspace,vscode,vscode/newWorkspace,create_new_workspace,#newWorkspace,high,writes,"Get setup steps to create project structures." +create_new_workspace,vscode,vscode/newWorkspace,create_new_workspace,#newWorkspace,high,writes,"Create a new workspace structure." get_vscode_api,vscode,vscode/vscodeAPI,get_vscode_api,#VSCodeAPI,low,none,"Get VS Code API documentation." -runSubagent,agent,agent/runSubagent,runSubagent,#runSubagent,high,mixed,"Launch a new agent for complex multi-step tasks." -get_selection,,selection,get_selection,#selection,low,reads,"Get current editor selection." +runSubagent,agent,agent/runSubagent,runSubagent,#runSubagent,high,mixed,"Launch a new agent for isolated subagent work." +get_selection,,selection,get_selection,#selection,low,reads,"Get the current editor selection." manage_todo_list,,todo,manage_todo_list,#todo,low,none,"Manage a structured todo list." >> RECOMMENDED_PLANNER_TOOLS: ["search/codebase", "search/fileSearch", "search/textSearch", "search/changes", "search/usages", "read/readFile", "read/problems", "todo", "web/fetch", "web/githubRepo"] -RECOMMENDED_IMPLEMENTER_TOOLS: ["search/codebase", "search/fileSearch", "search/textSearch", "read/readFile", "read/problems", "edit/createDirectory", "edit/createFile", "edit/editFiles", "execute/runInTerminal", "execute/getTerminalOutput", "todo", "web/fetch", "web/githubRepo", "agent/runSubagent"] +RECOMMENDED_IMPLEMENTER_TOOLS: ["search/codebase", "search/fileSearch", "search/textSearch", "read/readFile", "read/problems", "edit/createDirectory", "edit/createFile", "edit/editFiles", "execute/runInTerminal", "execute/getTerminalOutput", "todo", "web/fetch", "web/githubRepo", "agent", "agent/runSubagent"] -AGENT_MODELS: ["Claude Haiku 4.5 (copilot)", "Claude Opus 4.5 (copilot)", "Claude Sonnet 4 (copilot)", "Claude Sonnet 4.5 (copilot)", "Gemini 2.5 Pro (copilot)", "GPT-4.1 (copilot)"] +AGENT_MODELS: ["Claude Haiku 4.5 (copilot)", "Claude Opus 4.5 (copilot)", "Claude Sonnet 4 (copilot)", "Claude Sonnet 4.5 (copilot)", "Gemini 2.5 Pro (copilot)", "GPT-4.1 (copilot)", "GPT-5 (copilot)", "GPT-5.2 (copilot)"] AGENT_VERSIONING: JSON<< { "templates": [ { "path": "templates/.github/agents/aps-v{major}.{minor}.{patch}.agent.md", - "current_path": "templates/.github/agents/aps-v1.1.16.agent.md", + "current_path": "templates/.github/agents/aps-v1.2.1.agent.md", "frontmatter": { "name_pattern": "APS v{major}.{minor}.{patch} Agent", "description_pattern": "Generate APS v{major}.{minor}.{patch} .agent.md or .prompt.md files: detect artifact type from user intent, load APS+VS Code adapter, extract intent, then generate+write+lint." @@ -102,7 +144,9 @@ SKILL_AUTHORING_RESOURCES: JSON<< DOCS_AGENT_SKILLS_URL: "https://code.visualstudio.com/docs/copilot/customization/agent-skills" DOCS_PROMPT_FILES_URL: "https://code.visualstudio.com/docs/copilot/customization/prompt-files" +DOCS_MCP_URL: "https://code.visualstudio.com/docs/copilot/reference/mcp-configuration" DOCS_CUSTOM_AGENTS_URL: "https://code.visualstudio.com/docs/copilot/customization/custom-agents" +DOCS_SUBAGENTS_URL: "https://code.visualstudio.com/docs/copilot/agents/subagents" DOCS_TOOLS_IN_CHAT_URL: "https://code.visualstudio.com/docs/copilot/chat/chat-tools" DOCS_TOOLS_REFERENCE_URL: "https://code.visualstudio.com/docs/copilot/reference/copilot-vscode-features" DOCS_CUSTOM_INSTRUCTIONS_URL: "https://code.visualstudio.com/docs/copilot/customization/custom-instructions" @@ -113,19 +157,38 @@ DOCS_CUSTOM_INSTRUCTIONS_URL: "https://code.visualstudio.com/docs/copilot/custom --- name: description: "" +argument-hint: "" tools: +agents: +model: user-invocable: disable-model-invocation: target: +handoffs: + - label: "" + agent: + prompt: "" + send: + model: +mcp-servers: --- WHERE: -- is String; the agent identifier shown in UI. -- is String; single-line quoted string describing agent purpose. -- is YAML array of tool qualified names or toolset names from TOOLS constant. -- is Boolean; true if agent appears in the agents dropdown; default true. -- is Boolean; true to prevent invocation as subagent; default false. -- is one of: "vscode", "github-copilot"; default "vscode". +- is String; single-line double-quoted description shown in chat. +- is String; custom agent name. If omitted in a real file, the filename is used. +- is YAML array of agent names, `*`, or `[]`. If present, include `agent` or `agent/runSubagent` in . +- is String; optional hint shown in the chat input field. +- is Boolean; true to prevent this agent from being invoked as a subagent. +- is String; target agent identifier for the handoff. +- is String; button label shown after the response completes. +- is String; qualified model name such as `GPT-5.2 (copilot)`; omit to reuse the current model. +- is String; prompt text sent to the next agent. +- is Boolean; true to auto-submit the handoff prompt. +- is YAML array of MCP server config objects; only applicable for target `github-copilot`. +- is String or YAML array; use qualified model names in the format `Model Name (vendor)`. +- is one of: `vscode`, `github-copilot`; default `vscode`. +- is YAML array of qualified names or tool set values from TOOLS; no `#` prefix. +- is Boolean; true if the agent appears in the picker. @@ -136,9 +199,9 @@ tools: --- WHERE: -- is String; the prompt name shown in UI. -- is String; single-line quoted string describing what the prompt does. -- is YAML array of tool qualified names or toolset names from TOOLS constant. +- is String; single-line double-quoted description of what the prompt does. +- is String; prompt name shown in the UI. +- is YAML array of qualified names or tool set values from TOOLS. Include `agent` or `agent/runSubagent` when the prompt invokes a subagent. @@ -148,8 +211,8 @@ description: "" --- WHERE: -- is String; comma-separated glob patterns (e.g., "**/*.ts,**/*.tsx"). -- is String; describes the coding conventions in this file. +- is String; comma-separated glob patterns such as `**/*.ts,**/*.tsx`. +- is String; single-line double-quoted description of the coding conventions in this file. @@ -159,7 +222,7 @@ description: "" --- WHERE: -- is String; lowercase hyphenated skill identifier (e.g., "webapp-testing"). -- is String; specific description so Copilot can auto-load the skill when relevant. +- is String; single-line double-quoted string so Copilot can auto-load the skill when relevant. +- is String; lowercase hyphenated skill identifier such as `webapp-testing`. diff --git a/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/templates/.github/agents/aps-v1.1.16.agent.md b/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/templates/.github/agents/aps-v1.2.1.agent.md similarity index 98% rename from .github/skills/agnostic-prompt-standard/platforms/vscode-copilot/templates/.github/agents/aps-v1.1.16.agent.md rename to .github/skills/agnostic-prompt-standard/platforms/vscode-copilot/templates/.github/agents/aps-v1.2.1.agent.md index 5fe4f29..563daa1 100644 --- a/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/templates/.github/agents/aps-v1.1.16.agent.md +++ b/.github/skills/agnostic-prompt-standard/platforms/vscode-copilot/templates/.github/agents/aps-v1.2.1.agent.md @@ -1,6 +1,6 @@ --- -name: APS v1.1.16 Agent -description: "Generate APS v1.1.16 .agent.md or .prompt.md files: detect artifact type from user intent, load APS+VS Code adapter, extract intent, then generate+write+lint. Author: Christopher Buckley. Co-authors: Juan Burckhardt, Anastasiya Smirnova. URL: https://github.com/chris-buckley/agnostic-prompt-standard" +name: APS v1.2.1 Agent +description: "Generate APS v1.2.1 .agent.md or .prompt.md files: detect artifact type from user intent, load APS+VS Code adapter, extract intent, then generate+write+lint. Author: Christopher Buckley. Co-authors: Juan Burckhardt, Anastasiya Smirnova. URL: https://github.com/chris-buckley/agnostic-prompt-standard" tools: - execute/runInTerminal - read/readFile diff --git a/.github/skills/agnostic-prompt-standard/references/03-agentic-control.md b/.github/skills/agnostic-prompt-standard/references/03-agentic-control.md index 9339637..138b51e 100644 --- a/.github/skills/agnostic-prompt-standard/references/03-agentic-control.md +++ b/.github/skills/agnostic-prompt-standard/references/03-agentic-control.md @@ -180,6 +180,35 @@ MILESTONE "title" SNAP [SYM1, SYM2 ...] [delta=true|false] [redact=[SYM_A, SYM_B ...]] ``` +## External tools and MCP + +APS treats MCP tools and other external tools as normal tool names after the host engine registers +or aliases them. + +Rules: + +- A `USE` statement MUST reference the tool name that the engine exposes at runtime. +- The prompt MUST NOT declare transport, server URLs, headers, or MCP config inside `USE`. + Put those settings in external host files. +- Hosts MAY expose the raw MCP `Tool.name`, a host-decorated name, or a canonical APS alias. +- If a host uses decorated names (for example `mcp__docs__search_docs`), the engine SHOULD map + that runtime name to one stable APS tool id through external ALIAS config. +- A platform adapter MAY require a host-specific runtime name. In that case, the adapter decides the + final `tool_name` form. + +Examples: + +```text +USE `search_docs` where: query="adapter constants" +USE `mcp__docs__search_docs` where: query="adapter constants" +``` + +The two examples show different runtime naming styles. A host should expose one stable name to the +prompt at run time. + +For how to declare imported MCP signatures in `predefinedTools.json`, see **04 Schemas and +types**. + ## Arguments and values ```yaml diff --git a/.github/skills/agnostic-prompt-standard/references/04-schemas-and-types.md b/.github/skills/agnostic-prompt-standard/references/04-schemas-and-types.md index a1a98d1..64bdf12 100644 --- a/.github/skills/agnostic-prompt-standard/references/04-schemas-and-types.md +++ b/.github/skills/agnostic-prompt-standard/references/04-schemas-and-types.md @@ -117,6 +117,64 @@ Style guidelines: - Engines that emit `predefinedTools.json` SHOULD preserve or adopt the one-line-per-tool layout; engines MUST accept any valid JSON layout. +## MCP tool declaration pattern (external) + +Intent: let an engine import MCP tool signatures into `predefinedTools.json` without putting host +config inside the prompt. + +When an engine imports an MCP `Tool` from `tools/list`, it SHOULD: + +1. Create one canonical tool entry per MCP tool. +2. Use `Tool.name` as the canonical APS tool id unless a platform adapter requires a different + stable id. +3. Preserve `inputSchema` as the primary parameter contract. +4. Preserve `outputSchema` when it is present. +5. Derive the display label in this order: `title`, `annotations.title`, `name`. +6. Treat `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint` as advisory + metadata only. +7. Record MCP origin metadata such as the server id and original tool name. + +If a host exposes decorated runtime names (for example `mcp__server__tool`), the engine SHOULD: + +- keep one canonical tool object in `predefinedTools.json` +- map the decorated runtime name to the canonical APS tool id with `config.json` ALIAS entries +- avoid duplicate tool objects that differ only by host wrapper syntax. + +A collision between a host tool name, an MCP-imported tool name, or an ALIAS target/source MUST +raise `AG-034`. + +### Recommended object shape for `predefinedTools.json` + +This shape is RECOMMENDED for imported MCP tools. Engines MAY add extra fields. + +```json +{ + "name": "search_docs", + "displayName": "Search Docs", + "description": "Search the documentation site.", + "inputSchema": { "type": "object", "properties": { "query": { "type": "string" } }, "required": ["query"] }, + "outputSchema": { "type": "object", "properties": { "matches": { "type": "array" } } }, + "hints": { + "readOnly": true, + "destructive": false, + "idempotent": true, + "openWorld": true + }, + "source": { + "kind": "mcp", + "server": "docs", + "toolName": "search_docs" + } +} +``` + +Notes: + +- `name` is the canonical APS tool id. +- `displayName` is for humans and UI only. +- `hints` do not change the true behavior of a tool. They are advisory. +- `source` gives provenance for lint, IDE help, and debug output. + ## Example format contracts - Minimal error contract: [../assets/formats/format-error-v1.0.0.example.md](../assets/formats/format-error-v1.0.0.example.md) @@ -128,6 +186,8 @@ Style guidelines: - Code changes full: [../assets/formats/format-code-changes-full-v1.0.0.example.md](../assets/formats/format-code-changes-full-v1.0.0.example.md) - SMEAC plan: [../assets/formats/format-smeac-plan-v1.0.0.example.md](../assets/formats/format-smeac-plan-v1.0.0.example.md) +- MCP tool bridge example: [../assets/composites/mcp-tool-bridge-v1.0.0.example.md](../assets/composites/mcp-tool-bridge-v1.0.0.example.md) + ## Example constants - JSON block constant example: [../assets/constants/constants-json-block-v1.0.0.example.md](../assets/constants/constants-json-block-v1.0.0.example.md) diff --git a/README.md b/README.md index 6e61db4..63d16ec 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ This repository contains a _collection_ of Features. | OpenCode | https://opencode.ai/ | AI coding agent, built for the terminal. An open-source alternative to Claude Code with support for multiple LLM providers. | | Codex-cli | https://github.com/openai/codex | Codex CLI is an experimental project under active development. | | ccc | https://github.com/jsburckhardt/co-config | A TUI tool to interactively configure and view GitHub Copilot CLI settings. | +| Yazi | https://github.com/sxyazi/yazi | Blazing fast terminal file manager written in Rust, based on async I/O. | @@ -355,3 +356,20 @@ Running `ccc` inside the built container will print the version of ccc (Copilot ```bash ccc --version ``` + +### `yazi` + +Running `yazi --version` inside the built container will print the version of yazi. + +```jsonc +{ + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "features": { + "ghcr.io/jsburckhardt/devcontainer-features/yazi:1": {} + } +} +``` + +```bash +yazi --version +``` diff --git a/src/yazi/devcontainer-feature.json b/src/yazi/devcontainer-feature.json new file mode 100644 index 0000000..40adfd8 --- /dev/null +++ b/src/yazi/devcontainer-feature.json @@ -0,0 +1,13 @@ +{ + "name": "Yazi", + "id": "yazi", + "version": "1.0.0", + "description": "Blazing fast terminal file manager written in Rust, based on async I/O.", + "options": { + "version": { + "type": "string", + "default": "latest", + "description": "Version of yazi to install from GitHub releases e.g. v26.1.22" + } + } +} diff --git a/src/yazi/install.sh b/src/yazi/install.sh new file mode 100644 index 0000000..0ff729c --- /dev/null +++ b/src/yazi/install.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +# Variables +REPO_OWNER="sxyazi" +REPO_NAME="yazi" +BINARY_NAME="yazi" +YAZI_VERSION="${VERSION:-"latest"}" +GITHUB_API_REPO_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases" + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +# Clean up +rm -rf /var/lib/apt/lists/* + +# Checks if packages are installed and installs them if not +check_packages() { + if ! dpkg -s "$@" >/dev/null 2>&1; then + if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update -y + fi + apt-get -y install --no-install-recommends "$@" + fi +} + +# Make sure we have curl, jq, and unzip +check_packages curl jq ca-certificates unzip + +# Function to get the latest version from GitHub API +get_latest_version() { + curl -s "${GITHUB_API_REPO_URL}/latest" | jq -r ".tag_name" +} + +# Check if a version is passed as an argument +if [ -z "$YAZI_VERSION" ] || [ "$YAZI_VERSION" == "latest" ]; then + YAZI_VERSION=$(get_latest_version) + echo "No version provided or 'latest' specified, installing the latest version: $YAZI_VERSION" +else + echo "Installing version from environment variable: $YAZI_VERSION" +fi + +# Determine the OS and architecture +ARCH=$(uname -m) + +case "$ARCH" in + x86_64) + ARCH="x86_64" + ;; + aarch64) + ARCH="aarch64" + ;; + i686) + ARCH="i686" + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; +esac + +# Construct the download URL +# Asset pattern: yazi-{ARCH}-unknown-linux-gnu.zip +ASSET_NAME="${BINARY_NAME}-${ARCH}-unknown-linux-gnu" +DOWNLOAD_URL="https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${YAZI_VERSION}/${ASSET_NAME}.zip" + +# Create a temporary directory for the download +TMP_DIR=$(mktemp -d) +cd "$TMP_DIR" || exit + +echo "Downloading $BINARY_NAME from $DOWNLOAD_URL" +curl -sSL "$DOWNLOAD_URL" -o "${BINARY_NAME}.zip" + +# Extract the zip +echo "Extracting $BINARY_NAME..." +unzip -q "${BINARY_NAME}.zip" + +# Move the binaries to /usr/local/bin +echo "Installing $BINARY_NAME..." +mv "${ASSET_NAME}/${BINARY_NAME}" /usr/local/bin/ +mv "${ASSET_NAME}/ya" /usr/local/bin/ +chmod +x /usr/local/bin/$BINARY_NAME +chmod +x /usr/local/bin/ya + +# Cleanup +cd - || exit +rm -rf "$TMP_DIR" + +# Clean up +rm -rf /var/lib/apt/lists/* + +# Verify installation +echo "Verifying installation..." +$BINARY_NAME --version + +echo "Done!" diff --git a/test/_global/all-tools.sh b/test/_global/all-tools.sh index aef7f35..5676b52 100755 --- a/test/_global/all-tools.sh +++ b/test/_global/all-tools.sh @@ -19,5 +19,6 @@ check "codex" codex --version check "just" just --version check "opencode" opencode --version check "ccc" ccc --version +check "yazi" yazi --version reportResults diff --git a/test/_global/scenarios.json b/test/_global/scenarios.json index 58a9945..33acde0 100644 --- a/test/_global/scenarios.json +++ b/test/_global/scenarios.json @@ -20,7 +20,8 @@ "codex": {}, "just": {}, "opencode": {}, - "ccc": {} + "ccc": {}, + "yazi": {} } }, "flux-specific-version": { @@ -156,5 +157,13 @@ "version": "v0.1.5" } } + }, + "yazi-specific-version": { + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "features": { + "yazi": { + "version": "v26.1.22" + } + } } } diff --git a/test/_global/yazi-specific-version.sh b/test/_global/yazi-specific-version.sh new file mode 100644 index 0000000..517159c --- /dev/null +++ b/test/_global/yazi-specific-version.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e +source dev-container-features-test-lib +check "yazi with specific version" /bin/bash -c "yazi --version | grep '26.1.22'" + +reportResults diff --git a/test/yazi/test.sh b/test/yazi/test.sh new file mode 100644 index 0000000..fcf1fd1 --- /dev/null +++ b/test/yazi/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +source dev-container-features-test-lib +check "yazi" yazi --version +reportResults