mirror of https://github.com/garrytan/gstack.git
Fix Codex design binary path resolution
This commit is contained in:
parent
656df0e37e
commit
0d7c0617be
|
|
@ -42,14 +42,14 @@ const codex: HostConfig = {
|
||||||
],
|
],
|
||||||
|
|
||||||
runtimeRoot: {
|
runtimeRoot: {
|
||||||
globalSymlinks: ['bin', 'browse/dist', 'browse/bin', 'gstack-upgrade', 'ETHOS.md'],
|
globalSymlinks: ['bin', 'browse/dist', 'browse/bin', 'design/dist', 'gstack-upgrade', 'ETHOS.md'],
|
||||||
globalFiles: {
|
globalFiles: {
|
||||||
'review': ['checklist.md', 'TODOS-format.md'],
|
'review': ['checklist.md', 'TODOS-format.md'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sidecar: {
|
sidecar: {
|
||||||
path: '.agents/skills/gstack',
|
path: '.agents/skills/gstack',
|
||||||
symlinks: ['bin', 'browse', 'review', 'qa', 'ETHOS.md'],
|
symlinks: ['bin', 'browse', 'design', 'review', 'qa', 'ETHOS.md'],
|
||||||
},
|
},
|
||||||
|
|
||||||
install: {
|
install: {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,12 @@ import type { TemplateContext } from './types';
|
||||||
import { COMMAND_DESCRIPTIONS } from '../../browse/src/commands';
|
import { COMMAND_DESCRIPTIONS } from '../../browse/src/commands';
|
||||||
import { SNAPSHOT_FLAGS } from '../../browse/src/snapshot';
|
import { SNAPSHOT_FLAGS } from '../../browse/src/snapshot';
|
||||||
|
|
||||||
|
function resolveBinaryPath(dirExpr: string, binaryName: string): string {
|
||||||
|
return dirExpr.startsWith('$')
|
||||||
|
? `${dirExpr}/${binaryName}`
|
||||||
|
: `$HOME${dirExpr.replace(/^~/, '')}/${binaryName}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function generateCommandReference(_ctx: TemplateContext): string {
|
export function generateCommandReference(_ctx: TemplateContext): string {
|
||||||
// Group commands by category
|
// Group commands by category
|
||||||
const groups = new Map<string, Array<{ command: string; description: string; usage?: string }>>();
|
const groups = new Map<string, Array<{ command: string; description: string; usage?: string }>>();
|
||||||
|
|
@ -106,7 +112,7 @@ export function generateBrowseSetup(ctx: TemplateContext): string {
|
||||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||||
B=""
|
B=""
|
||||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse" ] && B="$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse"
|
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse" ] && B="$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse"
|
||||||
[ -z "$B" ] && B="$HOME${ctx.paths.browseDir.replace(/^~/, '')}/browse"
|
[ -z "$B" ] && B="${resolveBinaryPath(ctx.paths.browseDir, 'browse')}"
|
||||||
if [ -x "$B" ]; then
|
if [ -x "$B" ]; then
|
||||||
echo "READY: $B"
|
echo "READY: $B"
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
import type { TemplateContext } from './types';
|
import type { TemplateContext } from './types';
|
||||||
import { AI_SLOP_BLACKLIST, OPENAI_HARD_REJECTIONS, OPENAI_LITMUS_CHECKS } from './constants';
|
import { AI_SLOP_BLACKLIST, OPENAI_HARD_REJECTIONS, OPENAI_LITMUS_CHECKS } from './constants';
|
||||||
|
|
||||||
|
function resolveBinaryPath(dirExpr: string, binaryName: string): string {
|
||||||
|
return dirExpr.startsWith('$')
|
||||||
|
? `${dirExpr}/${binaryName}`
|
||||||
|
: `$HOME${dirExpr.replace(/^~/, '')}/${binaryName}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function generateDesignReviewLite(ctx: TemplateContext): string {
|
export function generateDesignReviewLite(ctx: TemplateContext): string {
|
||||||
const litmusList = OPENAI_LITMUS_CHECKS.map((item, i) => `${i + 1}. ${item}`).join(' ');
|
const litmusList = OPENAI_LITMUS_CHECKS.map((item, i) => `${i + 1}. ${item}`).join(' ');
|
||||||
const rejectionList = OPENAI_HARD_REJECTIONS.map((item, i) => `${i + 1}. ${item}`).join(' ');
|
const rejectionList = OPENAI_HARD_REJECTIONS.map((item, i) => `${i + 1}. ${item}`).join(' ');
|
||||||
|
|
@ -792,7 +798,7 @@ export function generateDesignSetup(ctx: TemplateContext): string {
|
||||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||||
D=""
|
D=""
|
||||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design" ] && D="$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design"
|
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design" ] && D="$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design"
|
||||||
[ -z "$D" ] && D="$HOME${ctx.paths.designDir.replace(/^~/, '')}/design"
|
[ -z "$D" ] && D="${resolveBinaryPath(ctx.paths.designDir, 'design')}"
|
||||||
if [ -x "$D" ]; then
|
if [ -x "$D" ]; then
|
||||||
echo "DESIGN_READY: $D"
|
echo "DESIGN_READY: $D"
|
||||||
else
|
else
|
||||||
|
|
@ -800,7 +806,7 @@ else
|
||||||
fi
|
fi
|
||||||
B=""
|
B=""
|
||||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse" ] && B="$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse"
|
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse" ] && B="$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse"
|
||||||
[ -z "$B" ] && B="$HOME${ctx.paths.browseDir.replace(/^~/, '')}/browse"
|
[ -z "$B" ] && B="${resolveBinaryPath(ctx.paths.browseDir, 'browse')}"
|
||||||
if [ -x "$B" ]; then
|
if [ -x "$B" ]; then
|
||||||
echo "BROWSE_READY: $B"
|
echo "BROWSE_READY: $B"
|
||||||
else
|
else
|
||||||
|
|
@ -837,7 +843,7 @@ export function generateDesignMockup(ctx: TemplateContext): string {
|
||||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||||
D=""
|
D=""
|
||||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design" ] && D="$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design"
|
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design" ] && D="$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design"
|
||||||
[ -z "$D" ] && D="$HOME${ctx.paths.designDir.replace(/^~/, '')}/design"
|
[ -z "$D" ] && D="${resolveBinaryPath(ctx.paths.designDir, 'design')}"
|
||||||
[ -x "$D" ] && echo "DESIGN_READY" || echo "DESIGN_NOT_AVAILABLE"
|
[ -x "$D" ] && echo "DESIGN_READY" || echo "DESIGN_NOT_AVAILABLE"
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
|
|
@ -1139,4 +1145,3 @@ Flat design can strip away useful visual information that signals interactivity.
|
||||||
Prioritize ruthlessly: things needed in a hurry go close at hand, everything
|
Prioritize ruthlessly: things needed in a hurry go close at hand, everything
|
||||||
else a few taps away with an obvious path to get there.`;
|
else a few taps away with an obvious path to get there.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
9
setup
9
setup
|
|
@ -532,7 +532,7 @@ link_codex_skill_dirs() {
|
||||||
|
|
||||||
# ─── Helper: create .agents/skills/gstack/ sidecar symlinks ──────────
|
# ─── Helper: create .agents/skills/gstack/ sidecar symlinks ──────────
|
||||||
# Codex/Gemini/Cursor read skills from .agents/skills/. We link runtime
|
# Codex/Gemini/Cursor read skills from .agents/skills/. We link runtime
|
||||||
# assets (bin/, browse/dist/, review/, qa/, etc.) so skill templates can
|
# assets (bin/, browse/dist/, design/dist/, review/, qa/, etc.) so skill templates can
|
||||||
# resolve paths like $SKILL_ROOT/review/design-checklist.md.
|
# resolve paths like $SKILL_ROOT/review/design-checklist.md.
|
||||||
create_agents_sidecar() {
|
create_agents_sidecar() {
|
||||||
local repo_root="$1"
|
local repo_root="$1"
|
||||||
|
|
@ -540,7 +540,7 @@ create_agents_sidecar() {
|
||||||
mkdir -p "$agents_gstack"
|
mkdir -p "$agents_gstack"
|
||||||
|
|
||||||
# Sidecar directories that skills reference at runtime
|
# Sidecar directories that skills reference at runtime
|
||||||
for asset in bin browse review qa; do
|
for asset in bin browse design review qa; do
|
||||||
local src="$SOURCE_GSTACK_DIR/$asset"
|
local src="$SOURCE_GSTACK_DIR/$asset"
|
||||||
local dst="$agents_gstack/$asset"
|
local dst="$agents_gstack/$asset"
|
||||||
if [ -d "$src" ] || [ -f "$src" ]; then
|
if [ -d "$src" ] || [ -f "$src" ]; then
|
||||||
|
|
@ -579,7 +579,7 @@ create_codex_runtime_root() {
|
||||||
rm -rf "$codex_gstack"
|
rm -rf "$codex_gstack"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$codex_gstack" "$codex_gstack/browse" "$codex_gstack/gstack-upgrade" "$codex_gstack/review"
|
mkdir -p "$codex_gstack" "$codex_gstack/browse" "$codex_gstack/design" "$codex_gstack/gstack-upgrade" "$codex_gstack/review"
|
||||||
|
|
||||||
if [ -f "$agents_dir/gstack/SKILL.md" ]; then
|
if [ -f "$agents_dir/gstack/SKILL.md" ]; then
|
||||||
ln -snf "$agents_dir/gstack/SKILL.md" "$codex_gstack/SKILL.md"
|
ln -snf "$agents_dir/gstack/SKILL.md" "$codex_gstack/SKILL.md"
|
||||||
|
|
@ -593,6 +593,9 @@ create_codex_runtime_root() {
|
||||||
if [ -d "$gstack_dir/browse/bin" ]; then
|
if [ -d "$gstack_dir/browse/bin" ]; then
|
||||||
ln -snf "$gstack_dir/browse/bin" "$codex_gstack/browse/bin"
|
ln -snf "$gstack_dir/browse/bin" "$codex_gstack/browse/bin"
|
||||||
fi
|
fi
|
||||||
|
if [ -d "$gstack_dir/design/dist" ]; then
|
||||||
|
ln -snf "$gstack_dir/design/dist" "$codex_gstack/design/dist"
|
||||||
|
fi
|
||||||
if [ -f "$agents_dir/gstack-upgrade/SKILL.md" ]; then
|
if [ -f "$agents_dir/gstack-upgrade/SKILL.md" ]; then
|
||||||
ln -snf "$agents_dir/gstack-upgrade/SKILL.md" "$codex_gstack/gstack-upgrade/SKILL.md"
|
ln -snf "$agents_dir/gstack-upgrade/SKILL.md" "$codex_gstack/gstack-upgrade/SKILL.md"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { describe, expect, test } from 'bun:test';
|
||||||
|
import type { TemplateContext } from '../scripts/resolvers/types';
|
||||||
|
import { HOST_PATHS } from '../scripts/resolvers/types';
|
||||||
|
import { generateBrowseSetup } from '../scripts/resolvers/browse';
|
||||||
|
import { generateDesignMockup, generateDesignSetup } from '../scripts/resolvers/design';
|
||||||
|
|
||||||
|
function makeCodexCtx(): TemplateContext {
|
||||||
|
return {
|
||||||
|
skillName: 'test-skill',
|
||||||
|
tmplPath: 'test.tmpl',
|
||||||
|
host: 'codex',
|
||||||
|
paths: HOST_PATHS.codex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Codex design/browse path generation', () => {
|
||||||
|
test('generated Codex browse setup uses GSTACK_BROWSE directly', () => {
|
||||||
|
const out = generateBrowseSetup(makeCodexCtx());
|
||||||
|
expect(out).toContain('B="$GSTACK_BROWSE/browse"');
|
||||||
|
expect(out).not.toContain('$HOME$GSTACK_BROWSE');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('generated Codex design setup uses GSTACK_DESIGN and GSTACK_BROWSE directly', () => {
|
||||||
|
const out = generateDesignSetup(makeCodexCtx());
|
||||||
|
expect(out).toContain('D="$GSTACK_DESIGN/design"');
|
||||||
|
expect(out).toContain('B="$GSTACK_BROWSE/browse"');
|
||||||
|
expect(out).not.toContain('$HOME$GSTACK_DESIGN');
|
||||||
|
expect(out).not.toContain('$HOME$GSTACK_BROWSE');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('generated Codex design mockup uses GSTACK_DESIGN directly', () => {
|
||||||
|
const out = generateDesignMockup(makeCodexCtx());
|
||||||
|
expect(out).toContain('D="$GSTACK_DESIGN/design"');
|
||||||
|
expect(out).not.toContain('$HOME$GSTACK_DESIGN');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -2188,12 +2188,13 @@ describe('setup script validation', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('create_agents_sidecar links runtime assets', () => {
|
test('create_agents_sidecar links runtime assets', () => {
|
||||||
// Sidecar must link bin, browse, review, qa
|
// Sidecar must link bin, browse, design, review, qa
|
||||||
const fnStart = setupContent.indexOf('create_agents_sidecar()');
|
const fnStart = setupContent.indexOf('create_agents_sidecar()');
|
||||||
const fnEnd = setupContent.indexOf('}', setupContent.indexOf('done', fnStart));
|
const fnEnd = setupContent.indexOf('}', setupContent.indexOf('done', fnStart));
|
||||||
const fnBody = setupContent.slice(fnStart, fnEnd);
|
const fnBody = setupContent.slice(fnStart, fnEnd);
|
||||||
expect(fnBody).toContain('bin');
|
expect(fnBody).toContain('bin');
|
||||||
expect(fnBody).toContain('browse');
|
expect(fnBody).toContain('browse');
|
||||||
|
expect(fnBody).toContain('design');
|
||||||
expect(fnBody).toContain('review');
|
expect(fnBody).toContain('review');
|
||||||
expect(fnBody).toContain('qa');
|
expect(fnBody).toContain('qa');
|
||||||
});
|
});
|
||||||
|
|
@ -2205,6 +2206,7 @@ describe('setup script validation', () => {
|
||||||
expect(fnBody).toContain('gstack/SKILL.md');
|
expect(fnBody).toContain('gstack/SKILL.md');
|
||||||
expect(fnBody).toContain('browse/dist');
|
expect(fnBody).toContain('browse/dist');
|
||||||
expect(fnBody).toContain('browse/bin');
|
expect(fnBody).toContain('browse/bin');
|
||||||
|
expect(fnBody).toContain('design/dist');
|
||||||
expect(fnBody).toContain('gstack-upgrade/SKILL.md');
|
expect(fnBody).toContain('gstack-upgrade/SKILL.md');
|
||||||
// Review runtime assets (individual files, not the whole dir)
|
// Review runtime assets (individual files, not the whole dir)
|
||||||
expect(fnBody).toContain('checklist.md');
|
expect(fnBody).toContain('checklist.md');
|
||||||
|
|
|
||||||
|
|
@ -350,6 +350,7 @@ describe('host-config-export.ts CLI', () => {
|
||||||
expect(exitCode).toBe(0);
|
expect(exitCode).toBe(0);
|
||||||
const lines = stdout.split('\n');
|
const lines = stdout.split('\n');
|
||||||
expect(lines).toContain('bin');
|
expect(lines).toContain('bin');
|
||||||
|
expect(lines).toContain('design/dist');
|
||||||
expect(lines).toContain('ETHOS.md');
|
expect(lines).toContain('ETHOS.md');
|
||||||
expect(lines).toContain('review/checklist.md');
|
expect(lines).toContain('review/checklist.md');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue