mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-09-14 20:16:53 +08:00
a84ae70e8c
* fix(init): use skill references for tools without a command adapter Adapterless tools (kimi, vibe, hermes, forgecode, codeartsagent, agents) skip command generation even under the default 'both' delivery, but their generated SKILL.md files still told agents to run /opsx:* commands that were never created, and the init summary suggested /opsx:propose. Route the existing skill-reference transform by command-surface capability so these tools get /openspec-* references, and point the getting-started hint at the skill when no selected tool got commands. Fixes #1155 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(init): address adversarial review findings for adapterless skill references - transform the committed skills.sh distribution too: pass transformToSkillReferences in generate-skillssh.mjs and the parity test, regenerate skills/ (that channel installs SKILL.md files only, so /opsx:* commands never exist there) - key the getting-started hint purely on whether any selected tool got commands, so the delivery=commands + adapterless corner can no longer print /opsx:propose - make the one-time profile-migration message capability-aware for projects whose detected tools have no command adapter - import CommandSurfaceCapability type-only instead of duplicating the union inline (a value import would close a module cycle) - cover the update path: the kimi migration test now asserts refreshed skills contain no /opsx references Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(init): honor Kimi Code's documented /skill: invocation syntax Per review: the blanket /openspec-* rewrite contradicted Kimi's documented invocation contract (/skill:openspec-*, see docs/supported-tools.md). Skill-reference transforms are now selected per tool via getSkillReferenceTransformer, with Kimi mapped to /skill:<name> and every other tool keeping the documented /<name> form; the getting-started hint and migration message use the same per-tool syntax. End-to-end Kimi assertions cover generated skill content, the refreshed update path, and the hint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(init): gate the getting-started hint on a generated surface Per review: with delivery=commands and only adapterless tools selected, init generated neither skills nor commands yet still advertised an invocation. Print a configuration correction instead, with the exact 'openspec config set delivery both' remedy, covered by an end-to-end commands-only adapterless test. Also from the adversarial review round: mixed selections that disagree on invocation syntax (kimi + vibe) now fall back to the default /openspec-* form in the shared hint and migration message instead of picking the first tool's syntax; add the missing changeset; correct the codex doc comment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(init): suppress the restart hint when no surface was generated From the third adversarial review round: the 'Restart your IDE for slash commands' line printed directly after the message saying nothing was generated. Gate it on an actually generated surface and pin that in the commands-only adapterless test. Also: use randomUUID() for init test temp dirs (matches update.test.ts, removes a theoretical Date.now collision), and clarify the changeset wording about the skills.sh channel's default reference form. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(init): print one usable getting-started hint per invocation syntax Per review: the mixed-syntax fallback advertised /openspec-propose, which Mistral Vibe accepts but Kimi Code does not. Group successful tools by their transformed reference and print one labeled hint line per distinct form, so every advertised instruction is usable by the tool it names; the mixed-tool test asserts exactly that. The migration message compares transformed outputs instead of function identities (also per review) and stays syntax-neutral ('the openspec-propose skill') when detected tools disagree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(init): keep codex hints syntax-neutral (skills-invocable, no slash surface) Codex has no slash-command surface: docs direct users to .codex/skills/openspec-*. The getting-started hint and the one-time migration message now name the skill ('the openspec-propose skill') instead of advertising a /openspec-* form Codex does not accept, and the restart line only claims slash commands when commands were generated. Hint lines are also limited to tools that actually got skills: under delivery=commands, codex+kimi previously advertised /skill:openspec-propose for Kimi while .kimi-code was never created. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(init): advertise a usable instruction for every configured tool Adversarial-review round fixes: - Mixed adapter-backed + skill-only selections (claude+kimi, claude+codex) printed a single unlabeled /opsx:propose hint that the skill-only tool cannot use; hints are now derived per tool from its generated surface and labeled when the selection disagrees. - The delivery=commands configuration correction keyed on the global aggregate, so a tool that got zero artifacts lost its correction as soon as any other tool generated something; it is now per-tool. - The migration message advertised /opsx:propose under an explicit 'delivery: skills' config where commands will never exist; the command form is now gated on the effective delivery. - Migration-message coverage extended (kimi, codex+kimi, delivery=skills, commands-installed); profile-describe init tests use randomUUID temp dirs like the first describe block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(update): derive migration and legacy-upgrade references per tool surface The one-time migration message collapsed mixed command + skill-only selections to /opsx:propose (Claude commands + a Kimi skill told the Kimi user to run a command it cannot invoke); the reference is now computed per detected tool and falls back to the syntax-neutral form on disagreement. The legacy-upgrade getting-started menu had the same capability blindness with hard-coded /opsx:new/continue/apply — a legacy Codex upgrade advertised commands Codex lost in #1283; menu lines are now derived the same way (byte-identical for command-tool upgrades). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
48 lines
1.8 KiB
JavaScript
48 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Generate the static skills.sh distribution of the OpenSpec workflow skills.
|
|
*
|
|
* skills.sh installs skills by reading committed `SKILL.md` files straight from
|
|
* a GitHub repo (`npx skills add Fission-AI/OpenSpec`). OpenSpec normally
|
|
* *generates* these skills into a user's project via `openspec init`, so this
|
|
* script mirrors that same output into a committed `skills/<name>/SKILL.md`
|
|
* tree that skills.sh can discover.
|
|
*
|
|
* The committed copies are kept honest by `test/core/templates/skillssh-parity.test.ts`,
|
|
* which regenerates and diffs against disk. Run this after any skill-template
|
|
* change: `pnpm build && pnpm generate:skills`.
|
|
*/
|
|
|
|
import { writeFileSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
import { getSkillTemplates, generateSkillContent } from '../dist/core/shared/skill-generation.js';
|
|
import { transformToSkillReferences } from '../dist/utils/command-references.js';
|
|
import {
|
|
cleanSkillSubdirectories,
|
|
prepareSkillDirectory,
|
|
stripVolatileFrontmatter,
|
|
SKILLS_DIR,
|
|
} from './skillssh-shared.mjs';
|
|
|
|
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
const outDir = join(repoRoot, SKILLS_DIR);
|
|
|
|
cleanSkillSubdirectories(outDir);
|
|
|
|
let count = 0;
|
|
for (const { template, dirName } of getSkillTemplates()) {
|
|
// skills.sh installs SKILL.md files only — no /opsx:* commands exist in
|
|
// that channel, so references must point at the skills themselves.
|
|
const content = stripVolatileFrontmatter(
|
|
generateSkillContent(template, 'skills.sh', transformToSkillReferences)
|
|
);
|
|
const skillDir = prepareSkillDirectory(outDir, dirName);
|
|
writeFileSync(join(skillDir, 'SKILL.md'), content, 'utf8');
|
|
count++;
|
|
}
|
|
|
|
console.log(`Generated ${count} skills into ${SKILLS_DIR}/`);
|