mirror of https://github.com/garrytan/gstack.git
fix: gen-skill-docs resolver merge + preamble tier gate + plan file discovery
The local RESOLVERS record in gen-skill-docs.ts was shadowing the imported canonical resolvers, causing stale test coverage and preamble generators to be used instead of the authoritative versions in resolvers/. Changes: - Merge imported RESOLVERS with local overrides (spread + override pattern) - Fix preamble tier gate: tier 1 skills no longer get AskUserQuestion format - Make plan file discovery host-agnostic (search multiple plan dirs) - Add missing E2E tier entries for ship/review plan completion tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ecb8ae658c
commit
b2e1ee9e7b
|
|
@ -16,7 +16,7 @@ import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import type { Host, TemplateContext } from './resolvers/types';
|
import type { Host, TemplateContext } from './resolvers/types';
|
||||||
import { HOST_PATHS } from './resolvers/types';
|
import { HOST_PATHS } from './resolvers/types';
|
||||||
import { RESOLVERS } from './resolvers/index';
|
import { RESOLVERS as IMPORTED_RESOLVERS } from './resolvers/index';
|
||||||
import { codexSkillName, transformFrontmatter, extractHookSafetyProse, extractNameAndDescription, condenseOpenAIShortDescription, generateOpenAIYaml } from './resolvers/codex-helpers';
|
import { codexSkillName, transformFrontmatter, extractHookSafetyProse, extractNameAndDescription, condenseOpenAIShortDescription, generateOpenAIYaml } from './resolvers/codex-helpers';
|
||||||
import { generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec } from './resolvers/review';
|
import { generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec } from './resolvers/review';
|
||||||
|
|
||||||
|
|
@ -473,7 +473,7 @@ Hey gstack team — ran into this while using /{skill-name}:
|
||||||
|
|
||||||
**What I was trying to do:** {what the user/agent was attempting}
|
**What I was trying to do:** {what the user/agent was attempting}
|
||||||
**What happened instead:** {what actually happened}
|
**What happened instead:** {what actually happened}
|
||||||
**My rating:** {0-10} — {one sentence on why it wasn't a 10}
|
**My Rating:** {0-10} — {one sentence on why it wasn't a 10}
|
||||||
|
|
||||||
## Steps to reproduce
|
## Steps to reproduce
|
||||||
1. {step}
|
1. {step}
|
||||||
|
|
@ -584,15 +584,14 @@ plan's living status.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generatePreamble(ctx: TemplateContext): string {
|
function generatePreamble(ctx: TemplateContext): string {
|
||||||
|
const tier = ctx.preambleTier ?? 4;
|
||||||
return [
|
return [
|
||||||
generatePreambleBash(ctx),
|
generatePreambleBash(ctx),
|
||||||
generateUpgradeCheck(ctx),
|
generateUpgradeCheck(ctx),
|
||||||
generateLakeIntro(),
|
generateLakeIntro(),
|
||||||
generateTelemetryPrompt(ctx),
|
generateTelemetryPrompt(ctx),
|
||||||
generateAskUserFormat(ctx),
|
...(tier >= 2 ? [generateAskUserFormat(ctx), generateCompletenessSection()] : []),
|
||||||
generateCompletenessSection(),
|
...(tier >= 3 ? [generateRepoModeSection(), generateSearchBeforeBuildingSection(ctx)] : []),
|
||||||
generateRepoModeSection(),
|
|
||||||
generateSearchBeforeBuildingSection(ctx),
|
|
||||||
generateContributorMode(),
|
generateContributorMode(),
|
||||||
generateCompletionStatus(),
|
generateCompletionStatus(),
|
||||||
].join('\n\n');
|
].join('\n\n');
|
||||||
|
|
@ -2801,37 +2800,20 @@ function generateSlugSetup(ctx: TemplateContext): string {
|
||||||
return `eval "$(${ctx.paths.binDir}/gstack-slug 2>/dev/null)" && mkdir -p ~/.gstack/projects/$SLUG`;
|
return `eval "$(${ctx.paths.binDir}/gstack-slug 2>/dev/null)" && mkdir -p ~/.gstack/projects/$SLUG`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use the canonical RESOLVERS from resolvers/index.ts, extended with local overrides.
|
||||||
|
// Local overrides are kept for functions that have hardcoded ~/.claude/ paths in the
|
||||||
|
// imported versions — the local versions are host-agnostic and safe for Codex output.
|
||||||
const RESOLVERS: Record<string, (ctx: TemplateContext) => string> = {
|
const RESOLVERS: Record<string, (ctx: TemplateContext) => string> = {
|
||||||
SLUG_EVAL: generateSlugEval,
|
...IMPORTED_RESOLVERS,
|
||||||
SLUG_SETUP: generateSlugSetup,
|
// Local override — preamble generator with tier-gated sections
|
||||||
COMMAND_REFERENCE: generateCommandReference,
|
|
||||||
SNAPSHOT_FLAGS: generateSnapshotFlags,
|
|
||||||
PREAMBLE: generatePreamble,
|
PREAMBLE: generatePreamble,
|
||||||
BROWSE_SETUP: generateBrowseSetup,
|
// Local overrides — these use host-agnostic paths (no ~/.claude/ hardcoding)
|
||||||
BASE_BRANCH_DETECT: generateBaseBranchDetect,
|
|
||||||
QA_METHODOLOGY: generateQAMethodology,
|
|
||||||
DESIGN_METHODOLOGY: generateDesignMethodology,
|
|
||||||
DESIGN_HARD_RULES: generateDesignHardRules,
|
|
||||||
DESIGN_OUTSIDE_VOICES: generateDesignOutsideVoices,
|
|
||||||
DESIGN_REVIEW_LITE: generateDesignReviewLite,
|
|
||||||
REVIEW_DASHBOARD: generateReviewDashboard,
|
|
||||||
PLAN_FILE_REVIEW_REPORT: generatePlanFileReviewReport,
|
PLAN_FILE_REVIEW_REPORT: generatePlanFileReviewReport,
|
||||||
TEST_BOOTSTRAP: generateTestBootstrap,
|
|
||||||
TEST_COVERAGE_AUDIT_PLAN: generateTestCoverageAuditPlan,
|
|
||||||
TEST_COVERAGE_AUDIT_SHIP: generateTestCoverageAuditShip,
|
|
||||||
TEST_COVERAGE_AUDIT_REVIEW: generateTestCoverageAuditReview,
|
|
||||||
TEST_FAILURE_TRIAGE: generateTestFailureTriage,
|
|
||||||
SPEC_REVIEW_LOOP: generateSpecReviewLoop,
|
|
||||||
DESIGN_SKETCH: generateDesignSketch,
|
|
||||||
BENEFITS_FROM: generateBenefitsFrom,
|
|
||||||
CODEX_SECOND_OPINION: generateCodexSecondOpinion,
|
|
||||||
CODEX_REVIEW_STEP: generateAdversarialStep,
|
|
||||||
ADVERSARIAL_STEP: generateAdversarialStep,
|
|
||||||
DEPLOY_BOOTSTRAP: generateDeployBootstrap,
|
|
||||||
CODEX_PLAN_REVIEW: generateCodexPlanReview,
|
|
||||||
PLAN_COMPLETION_AUDIT_SHIP: generatePlanCompletionAuditShip,
|
PLAN_COMPLETION_AUDIT_SHIP: generatePlanCompletionAuditShip,
|
||||||
PLAN_COMPLETION_AUDIT_REVIEW: generatePlanCompletionAuditReview,
|
PLAN_COMPLETION_AUDIT_REVIEW: generatePlanCompletionAuditReview,
|
||||||
PLAN_VERIFICATION_EXEC: generatePlanVerificationExec,
|
PLAN_VERIFICATION_EXEC: generatePlanVerificationExec,
|
||||||
|
// Local-only entry not in resolvers/index.ts
|
||||||
|
CODEX_REVIEW_STEP: generateAdversarialStep,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ─── Codex Helpers ───────────────────────────────────────────
|
// ─── Codex Helpers ───────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -598,19 +598,21 @@ SOURCE = "codex" if Codex ran, "claude" if subagent ran.
|
||||||
function generatePlanFileDiscovery(): string {
|
function generatePlanFileDiscovery(): string {
|
||||||
return `### Plan File Discovery
|
return `### Plan File Discovery
|
||||||
|
|
||||||
1. **Conversation context (primary):** Check if there is an active plan file in this conversation — Claude Code system messages include plan file paths when in plan mode. Look for references like \`~/.claude/plans/*.md\` in system messages. If found, use it directly — this is the most reliable signal.
|
1. **Conversation context (primary):** Check if there is an active plan file in this conversation. The host agent's system messages include plan file paths when in plan mode. If found, use it directly — this is the most reliable signal.
|
||||||
|
|
||||||
2. **Content-based search (fallback):** If no plan file is referenced in conversation context, search by content:
|
2. **Content-based search (fallback):** If no plan file is referenced in conversation context, search by content:
|
||||||
|
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
BRANCH=$(git branch --show-current 2>/dev/null | tr '/' '-')
|
BRANCH=$(git branch --show-current 2>/dev/null | tr '/' '-')
|
||||||
REPO=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)")
|
REPO=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)")
|
||||||
# Try branch name match first (most specific)
|
# Search common plan file locations
|
||||||
PLAN=$(ls -t ~/.claude/plans/*.md 2>/dev/null | xargs grep -l "$BRANCH" 2>/dev/null | head -1)
|
for PLAN_DIR in "$HOME/.claude/plans" "$HOME/.codex/plans" ".gstack/plans"; do
|
||||||
# Fall back to repo name match
|
[ -d "$PLAN_DIR" ] || continue
|
||||||
[ -z "$PLAN" ] && PLAN=$(ls -t ~/.claude/plans/*.md 2>/dev/null | xargs grep -l "$REPO" 2>/dev/null | head -1)
|
PLAN=$(ls -t "$PLAN_DIR"/*.md 2>/dev/null | xargs grep -l "$BRANCH" 2>/dev/null | head -1)
|
||||||
# Last resort: most recent plan modified in the last 24 hours
|
[ -z "$PLAN" ] && PLAN=$(ls -t "$PLAN_DIR"/*.md 2>/dev/null | xargs grep -l "$REPO" 2>/dev/null | head -1)
|
||||||
[ -z "$PLAN" ] && PLAN=$(find ~/.claude/plans -name '*.md' -mmin -1440 -maxdepth 1 2>/dev/null | xargs ls -t 2>/dev/null | head -1)
|
[ -z "$PLAN" ] && PLAN=$(find "$PLAN_DIR" -name '*.md' -mmin -1440 -maxdepth 1 2>/dev/null | xargs ls -t 2>/dev/null | head -1)
|
||||||
|
[ -n "$PLAN" ] && break
|
||||||
|
done
|
||||||
[ -n "$PLAN" ] && echo "PLAN_FILE: $PLAN" || echo "NO_PLAN_FILE"
|
[ -n "$PLAN" ] && echo "PLAN_FILE: $PLAN" || echo "NO_PLAN_FILE"
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ export const E2E_TIERS: Record<string, 'gate' | 'periodic'> = {
|
||||||
'review-base-branch': 'gate',
|
'review-base-branch': 'gate',
|
||||||
'review-design-lite': 'periodic', // 4/7 threshold is subjective
|
'review-design-lite': 'periodic', // 4/7 threshold is subjective
|
||||||
'review-coverage-audit': 'gate',
|
'review-coverage-audit': 'gate',
|
||||||
|
'review-plan-completion': 'gate',
|
||||||
|
|
||||||
// Office Hours
|
// Office Hours
|
||||||
'office-hours-spec-review': 'gate',
|
'office-hours-spec-review': 'gate',
|
||||||
|
|
@ -208,6 +209,8 @@ export const E2E_TIERS: Record<string, 'gate' | 'periodic'> = {
|
||||||
'ship-local-workflow': 'gate',
|
'ship-local-workflow': 'gate',
|
||||||
'ship-coverage-audit': 'gate',
|
'ship-coverage-audit': 'gate',
|
||||||
'ship-triage': 'gate',
|
'ship-triage': 'gate',
|
||||||
|
'ship-plan-completion': 'gate',
|
||||||
|
'ship-plan-verification': 'gate',
|
||||||
|
|
||||||
// Retro — gate for cheap branch detection, periodic for full Opus retro
|
// Retro — gate for cheap branch detection, periodic for full Opus retro
|
||||||
'retro': 'periodic',
|
'retro': 'periodic',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue