mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 14:06:50 +01:00
C5: OpenCode /gstack-* commands load the skill by its frontmatter name
OpenCode's skill tool knows gstack-review as `review` (its frontmatter name), and OpenCode's builtin /review shadows that name as a command. The managed /gstack-review command told the agent to load `gstack-review`, a name the skill tool does not list. Every managed command now names the frontmatter name. OpenCode's AskUserQuestion/ExitPlanMode mapping (#2759) already shipped in v1.91.16.0. Test migration: the #2629 commands test pinned the directory name. Co-authored-by: Lockyer <135391289+Lockyer228@users.noreply.github.com>
This commit is contained in:
1 parent
f2838fd7d0
commit
82a79be3f2
2 files changed
+11
-3
No files matched your search
@@ -2942,7 +2942,7 @@ link_cursor_skill_dirs() {
|
||||
# marker is the user's and is never touched; managed files whose skill is gone
|
||||
# or disabled are removed.
|
||||
write_opencode_commands() {
|
||||
local skills_dir="$1/.opencode/skills" cmd_dir="$2" d name file desc marker
|
||||
local skills_dir="$1/.opencode/skills" cmd_dir="$2" d name file desc marker skill
|
||||
marker='<!-- gstack-managed command (./setup --host opencode): edits are overwritten -->'
|
||||
mkdir -p "$cmd_dir"
|
||||
for d in "$skills_dir"/gstack-*/; do
|
||||
@@ -2955,8 +2955,11 @@ write_opencode_commands() {
|
||||
fi
|
||||
case "${_DISABLED_SKILLS:- }" in *" ${name#gstack-} "*) rm -f "$file"; continue ;; esac
|
||||
desc="$(awk '/^description:/ { f = 1; next } f && /^[^ ]/ { exit } f && NF { sub(/^ +/, ""); print; exit }' "$d/SKILL.md" | sed 's/\\/\\\\/g; s/"/\\"/g')"
|
||||
# The skill tool knows a skill by its frontmatter name (gstack-review's is
|
||||
# `review`, which OpenCode's builtin /review shadows as a command, #2651).
|
||||
skill="$(awk '/^---$/ { fm++; next } fm == 1 && $1 == "name:" { print $2; exit }' "$d/SKILL.md")"
|
||||
printf -- '---\ndescription: "%s"\nagent: build\nsubtask: false\n---\n%s\nLoad the `%s` skill with the skill tool and follow its instructions.\n\n$ARGUMENTS\n' \
|
||||
"${desc:-gstack $name}" "$marker" "$name" > "$file.tmp.$$" && mv -f "$file.tmp.$$" "$file"
|
||||
"${desc:-gstack $name}" "$marker" "${skill:-$name}" > "$file.tmp.$$" && mv -f "$file.tmp.$$" "$file"
|
||||
done
|
||||
for file in "$cmd_dir"/gstack-*.md; do
|
||||
[ -f "$file" ] && grep -qF "$marker" "$file" 2>/dev/null || continue
|
||||
|
||||
@@ -131,6 +131,10 @@ describe.skipIf(process.platform === 'win32')('host conformance kit', () => {
|
||||
expect(status.status).toBe(0);
|
||||
expect(status.stdout).toMatch(new RegExp(`\\b${host}\\s+${ALL_HOST_CONFIGS.find(c => c.name === host)!.tier}\\s+global\\s+current`));
|
||||
|
||||
// C5 (#2651): OpenCode's builtin /review shadows the review skill, so
|
||||
// /gstack-review loads it by the name the skill tool knows.
|
||||
if (host === 'opencode') expect(readFileSync(join(f.home, '.config/opencode/commands/gstack-review.md'), 'utf8')).toContain('Load the `review` skill with the skill tool');
|
||||
|
||||
// INV-3 install-level checks (C2, C3, ENG-1, ENG-14).
|
||||
if (host !== 'claude') {
|
||||
const runtimeRoot = rows[0][4];
|
||||
@@ -154,7 +158,8 @@ describe.skipIf(process.platform === 'win32')('host conformance kit', () => {
|
||||
expect(runSetup(f, join(src, 'setup'), ['--host', 'opencode']).status).toBe(0);
|
||||
const ship = readFileSync(join(commands, 'gstack-ship.md'), 'utf8');
|
||||
expect(ship).toMatch(/^---\ndescription: "[^"]+"\nagent: build\nsubtask: false\n---\n/);
|
||||
expect(ship).toContain('Load the `gstack-ship` skill with the skill tool');
|
||||
// The skill tool loads by frontmatter name, not directory name (#2651).
|
||||
expect(ship).toContain('Load the `ship` skill with the skill tool');
|
||||
expect(ship).toContain('$ARGUMENTS');
|
||||
expect(readFileSync(join(commands, 'gstack-review.md'), 'utf8')).toBe('my own review command\n');
|
||||
expect(existsSync(join(commands, 'gstack-retired.md'))).toBe(false);
|
||||
|
||||
Reference in new issue
Block a user