feat(kyberforge): retarget forge skills to author/audit APM content #93
@@ -42,7 +42,7 @@ scripts/vale-wrap.sh <path-to-apm-agent-file> # plugin/APM sco
|
|||||||
|
|
||||||
The script accepts either the CC file, the Copilot file, or (at plugin/APM scope) the single `.apm/agents/<name>.agent.md` file. It detects provider from extension and scope from the walk-up above, then runs the checks for that scope.
|
The script accepts either the CC file, the Copilot file, or (at plugin/APM scope) the single `.apm/agents/<name>.agent.md` file. It detects provider from extension and scope from the walk-up above, then runs the checks for that scope.
|
||||||
|
|
||||||
At **project/user scope** it derives the counterpart and runs the existing pair-based checks. Note FAILs and SUGGESTIONs for the `### Structure` and `### Provider safety` report dimensions. Findings about missing fields, bad name format, empty body, or missing frontmatter → `### Structure`. Findings about CC-only fields in a Copilot file, Copilot-only fields in a CC file, plugin-silently-ignored fields, body length, or subagent-unavailable tools → `### Provider safety`. A missing counterpart file → `### Pair consistency`.
|
At **project/user scope** it derives the counterpart and runs the existing pair-based checks. Note FAILs and SUGGESTIONs for the `### Structure` and `### Provider safety` report dimensions. Findings about missing fields, bad name format, empty body, or missing frontmatter → `### Structure`. Findings about CC-only fields in a Copilot file, Copilot-only fields in a CC file, body length, or subagent-unavailable tools → `### Provider safety`. A missing counterpart file → `### Pair consistency`.
|
||||||
|
|
||||||
At **plugin/APM scope** there is no counterpart — the script instead checks the single file's frontmatter against the `apm-agent-allowlist` in `references/field-inventory.md` (`name`, `description`, `model` — nothing else). Findings about missing fields, bad name format, name/filename-stem mismatch, empty body, or missing frontmatter → `### Structure`, same as project/user scope. Findings about any field outside the allowlist (e.g. `tools`, or any Claude-only/Copilot-only field carried over from a hand-edit) and body length → `### Provider safety` — but the dimension's meaning shifts here: it is no longer a CC-vs-Copilot field-leakage check, it's a vendor-neutral-field-allowlist check, since `apm compile` verbatim-copies this file's frontmatter to every target and there is no per-target integrator to reconcile a CC-only or Copilot-only field (ADR-0016). `### Pair consistency` never applies at this scope — the script never emits a missing-counterpart FAIL here, because there is nothing to pair by design.
|
At **plugin/APM scope** there is no counterpart — the script instead checks the single file's frontmatter against the `apm-agent-allowlist` in `references/field-inventory.md` (`name`, `description`, `model` — nothing else). Findings about missing fields, bad name format, name/filename-stem mismatch, empty body, or missing frontmatter → `### Structure`, same as project/user scope. Findings about any field outside the allowlist (e.g. `tools`, or any Claude-only/Copilot-only field carried over from a hand-edit) and body length → `### Provider safety` — but the dimension's meaning shifts here: it is no longer a CC-vs-Copilot field-leakage check, it's a vendor-neutral-field-allowlist check, since `apm compile` verbatim-copies this file's frontmatter to every target and there is no per-target integrator to reconcile a CC-only or Copilot-only field (ADR-0016). `### Pair consistency` never applies at this scope — the script never emits a missing-counterpart FAIL here, because there is nothing to pair by design.
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ name description tools disallowedTools model effort maxTurns permissionMode skil
|
|||||||
|
|
||||||
maxTurns isolation memory permissionMode effort hooks mcpServers disallowedTools skills initialPrompt color background
|
maxTurns isolation memory permissionMode effort hooks mcpServers disallowedTools skills initialPrompt color background
|
||||||
|
|
||||||
## plugin-silently-ignored-fields
|
|
||||||
|
|
||||||
hooks mcpServers permissionMode
|
|
||||||
|
|
||||||
## copilot-fields
|
## copilot-fields
|
||||||
|
|
||||||
name description tools target model disable-model-invocation user-invocable mcp-servers metadata
|
name description tools target model disable-model-invocation user-invocable mcp-servers metadata
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ def parse_section_tokens(content, section_name):
|
|||||||
|
|
||||||
cc_only_fields = parse_section_tokens(inv_content, 'claude-code-only-fields')
|
cc_only_fields = parse_section_tokens(inv_content, 'claude-code-only-fields')
|
||||||
copilot_only_fields = parse_section_tokens(inv_content, 'copilot-only-fields')
|
copilot_only_fields = parse_section_tokens(inv_content, 'copilot-only-fields')
|
||||||
plugin_ignored_fields = parse_section_tokens(inv_content, 'plugin-silently-ignored-fields')
|
|
||||||
apm_agent_allowlist = parse_section_tokens(inv_content, 'apm-agent-allowlist')
|
apm_agent_allowlist = parse_section_tokens(inv_content, 'apm-agent-allowlist')
|
||||||
|
|
||||||
# Tools the runtime withholds from subagents regardless of the tools field
|
# Tools the runtime withholds from subagents regardless of the tools field
|
||||||
@@ -239,7 +238,7 @@ else: # user
|
|||||||
counterpart = os.path.join(home, '.claude', 'agents', name_stem + '.md')
|
counterpart = os.path.join(home, '.claude', 'agents', name_stem + '.md')
|
||||||
counterpart_provider = 'claude-code'
|
counterpart_provider = 'claude-code'
|
||||||
|
|
||||||
def check_file(fpath, file_provider, is_plugin_scope):
|
def check_file(fpath, file_provider):
|
||||||
local_fname = os.path.basename(fpath)
|
local_fname = os.path.basename(fpath)
|
||||||
with open(fpath) as f:
|
with open(fpath) as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
@@ -299,13 +298,6 @@ def check_file(fpath, file_provider, is_plugin_scope):
|
|||||||
if key in copilot_only_fields:
|
if key in copilot_only_fields:
|
||||||
fail(f"Copilot-only field '{key}' present in CC file — {local_fname}")
|
fail(f"Copilot-only field '{key}' present in CC file — {local_fname}")
|
||||||
|
|
||||||
# Silently-ignored fields in plugin-scope CC file
|
|
||||||
if file_provider == 'claude-code' and is_plugin_scope:
|
|
||||||
fm_keys = get_frontmatter_keys(fm)
|
|
||||||
for key in sorted(fm_keys):
|
|
||||||
if key in plugin_ignored_fields:
|
|
||||||
fail(f"plugin-silently-ignored field '{key}' present in plugin-scope CC file — {local_fname}")
|
|
||||||
|
|
||||||
# Subagent-unavailable tools listed in tools field
|
# Subagent-unavailable tools listed in tools field
|
||||||
tools = extract_tools_list(fm)
|
tools = extract_tools_list(fm)
|
||||||
unavailable = tools & SUBAGENT_UNAVAILABLE_TOOLS
|
unavailable = tools & SUBAGENT_UNAVAILABLE_TOOLS
|
||||||
@@ -318,9 +310,8 @@ if not os.path.isfile(counterpart):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# --- Check both files ---
|
# --- Check both files ---
|
||||||
is_plugin = (scope == 'plugin')
|
check_file(agent_file, provider)
|
||||||
check_file(agent_file, provider, is_plugin)
|
check_file(counterpart, counterpart_provider)
|
||||||
check_file(counterpart, counterpart_provider, is_plugin)
|
|
||||||
|
|
||||||
for s in suggestions:
|
for s in suggestions:
|
||||||
print(f"SUGGESTION {s}")
|
print(f"SUGGESTION {s}")
|
||||||
|
|||||||
Reference in New Issue
Block a user