fix: resolve merge conflicts with main, keep branch review architecture
- Remove duplicate extractBundledSkill from generated builtin.ts template - Keep extract-to-disk extension.ts (branch version) - Keep SSH clone URL for generate-review-builtin - Revert .gitignore, package.json, locales to branch versions Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
8599340c68
commit
a645f34ee5
13
.gitignore
vendored
13
.gitignore
vendored
|
|
@ -49,4 +49,15 @@ src/costrict/review/skill/builtin.ts
|
|||
|
||||
# Review builtin cache
|
||||
packages/builtin-tools/bundled-review/
|
||||
bundled-review/
|
||||
|
||||
# Upstream additions
|
||||
teach-me
|
||||
credentials.json
|
||||
|
||||
# Session-scoped progress / state files written by agents and skills
|
||||
.claude-impl-state.md
|
||||
.claude-progress.md
|
||||
.claude-recovery.md
|
||||
.test-progress.md
|
||||
.squash-tmp/
|
||||
.git.*-backup
|
||||
|
|
@ -41,7 +41,6 @@
|
|||
],
|
||||
"scripts": {
|
||||
"build": "bun run build.ts",
|
||||
"build:builtin-review": "bun run scripts/generate-review-builtin.ts",
|
||||
"build:vite": "vite build && bun run scripts/post-build.ts",
|
||||
"build:vite:only": "vite build",
|
||||
"build:bun": "bun run build.ts",
|
||||
|
|
@ -207,6 +206,7 @@
|
|||
"turndown": "^7.2.2",
|
||||
"type-fest": "^5.5.0",
|
||||
"typescript": "^6.0.2",
|
||||
"undici": "^7.24.6",
|
||||
"url-handler-napi": "workspace:*",
|
||||
"usehooks-ts": "^3.1.1",
|
||||
"vite": "^8.0.8",
|
||||
|
|
|
|||
|
|
@ -293,26 +293,6 @@ export async function extractBundledSkill(skillName: string, targetDir: string,
|
|||
await writeFile(join(targetDir, relativePath), content, "utf-8")
|
||||
}
|
||||
}
|
||||
|
||||
export async function extractBundledSkill(skillName: string, targetDir: string, locale: string): Promise<void> {
|
||||
const localeData = SKILL_FILES[locale]
|
||||
if (!localeData) {
|
||||
throw new Error(\`Locale not found: \${locale}\`)
|
||||
}
|
||||
|
||||
const skillFiles = localeData[skillName]
|
||||
if (!skillFiles) {
|
||||
throw new Error(\`Skill not found: \${skillName}\`)
|
||||
}
|
||||
|
||||
const { mkdir: mkdirSync, writeFile: writeFileSync } = await import('fs/promises')
|
||||
const { join: pathJoin, dirname: pathDirname } = await import('path')
|
||||
await mkdirSync(targetDir, { recursive: true })
|
||||
for (const [relativePath, fileContent] of Object.entries(skillFiles)) {
|
||||
await mkdirSync(pathJoin(targetDir, pathDirname(relativePath)), { recursive: true })
|
||||
await writeFileSync(pathJoin(targetDir, relativePath), fileContent, 'utf-8')
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
await mkdir(path.dirname(builtinSkillsFile), { recursive: true })
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type { ToolUseContext } from '../../Tool.js'
|
||||
import { clearCommandsCache } from '../../commands.js'
|
||||
import type {
|
||||
LocalJSXCommandContext,
|
||||
LocalJSXCommandOnDone,
|
||||
|
|
@ -10,7 +9,6 @@ import {
|
|||
getLanguageDisplayName,
|
||||
getResolvedLanguage,
|
||||
} from '../../utils/language.js'
|
||||
import { Extension as ReviewExtension } from '../../costrict/review/index.js'
|
||||
|
||||
const VALID_LANGS: readonly PreferredLanguage[] = ['en', 'zh', 'auto']
|
||||
|
||||
|
|
@ -42,10 +40,6 @@ export async function call(
|
|||
const lang = arg as PreferredLanguage
|
||||
saveGlobalConfig(current => ({ ...current, preferredLanguage: lang }))
|
||||
|
||||
// Re-extract review skills for the new locale and refresh skill caches
|
||||
await ReviewExtension.initializeBuiltinSkills().catch(() => {})
|
||||
clearCommandsCache()
|
||||
|
||||
const resolved = getResolvedLanguage()
|
||||
const suffix = lang === 'auto' ? ` → ${getLanguageDisplayName(resolved)}` : ''
|
||||
onDone(`Language set to ${getLanguageDisplayName(lang)}${suffix}`, {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Code Review
|
||||
|
||||
Please use the Skill tool to load the `review` skill to perform a code review on: $ARGUMENTS
|
||||
Please perform a code review on: $ARGUMENTS
|
||||
|
||||
Please respond and write all files in English throughout the entire process.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# 代码审查
|
||||
|
||||
请使用 Skill 工具加载 `review` 技能来对以下内容执行代码审查:$ARGUMENTS
|
||||
请对以下内容执行代码审查:$ARGUMENTS
|
||||
|
||||
全程请使用中文进行回答与文件写入。
|
||||
|
|
|
|||
|
|
@ -1,72 +1,87 @@
|
|||
import { mkdir, readFile, writeFile } from 'fs/promises'
|
||||
import { join } from 'path'
|
||||
import { getClaudeConfigHomeDir } from 'src/utils/envUtils.js'
|
||||
/**
|
||||
* CoStrict Skill Extension
|
||||
*
|
||||
* Initializes builtin review skills by extracting them from embedded
|
||||
* SKILL_FILES to a cache directory on disk.
|
||||
*
|
||||
* Version tracking uses commit SHA + locale in a .version file.
|
||||
* Skills are re-extracted when version or locale changes.
|
||||
*/
|
||||
|
||||
import path from 'path'
|
||||
import { writeFile, readFile, rm, mkdir, stat } from 'fs/promises'
|
||||
import { getResolvedLanguage } from 'src/utils/language.js'
|
||||
import {
|
||||
extractBundledSkill,
|
||||
getBuiltinSkillVersion,
|
||||
listBuiltinSkillNames,
|
||||
} from './skill/builtin.js'
|
||||
import * as Builtin from './skill/builtin.js'
|
||||
|
||||
const LOCALE_MAP: Record<string, string> = { zh: 'zh-CN', en: 'en' }
|
||||
|
||||
function getLocale(): string {
|
||||
const lang = getResolvedLanguage()
|
||||
return LOCALE_MAP[lang] ?? 'zh-CN'
|
||||
}
|
||||
|
||||
function getReviewSkillsDir(): string {
|
||||
return join(getClaudeConfigHomeDir(), 'skills')
|
||||
function getSkillCacheDir(): string {
|
||||
const home = process.env.HOME ?? process.env.USERPROFILE ?? ''
|
||||
return path.join(home, '.claude', 'skills')
|
||||
}
|
||||
|
||||
function getVersionFilePath(skillDir: string): string {
|
||||
return join(skillDir, '.version')
|
||||
return path.join(skillDir, '.version')
|
||||
}
|
||||
|
||||
async function getInstalledVersion(skillDir: string): Promise<string | null> {
|
||||
try {
|
||||
return await readFile(getVersionFilePath(skillDir), 'utf-8')
|
||||
const content = await readFile(getVersionFilePath(skillDir), 'utf-8')
|
||||
return content.trim()
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function writeVersionFile(
|
||||
skillDir: string,
|
||||
skillName: string,
|
||||
locale: string,
|
||||
): Promise<void> {
|
||||
const builtinVersion = getBuiltinSkillVersion(skillName)
|
||||
async function needsUpdate(skillDir: string, skillName: string, locale: string): Promise<boolean> {
|
||||
const builtinVersion = Builtin.getBuiltinSkillVersion(skillName)
|
||||
if (!builtinVersion) return true
|
||||
|
||||
const installedVersion = await getInstalledVersion(skillDir)
|
||||
const expectedVersion = `${builtinVersion}:${locale}`
|
||||
return installedVersion !== expectedVersion
|
||||
}
|
||||
|
||||
async function writeVersionFile(skillDir: string, skillName: string, locale: string): Promise<void> {
|
||||
const builtinVersion = Builtin.getBuiltinSkillVersion(skillName)
|
||||
if (!builtinVersion) return
|
||||
|
||||
await mkdir(skillDir, { recursive: true })
|
||||
await writeFile(getVersionFilePath(skillDir), `${builtinVersion}:${locale}`, 'utf-8')
|
||||
}
|
||||
|
||||
async function needsUpdate(
|
||||
skillDir: string,
|
||||
skillName: string,
|
||||
locale: string,
|
||||
): Promise<boolean> {
|
||||
const builtinVersion = getBuiltinSkillVersion(skillName)
|
||||
if (!builtinVersion) return true
|
||||
const installed = await getInstalledVersion(skillDir)
|
||||
return installed !== `${builtinVersion}:${locale}`
|
||||
}
|
||||
|
||||
export async function initializeBuiltinSkills(): Promise<void> {
|
||||
const locale = getLocale()
|
||||
const skillsDir = getReviewSkillsDir()
|
||||
const skillNames = listBuiltinSkillNames()
|
||||
const lang = getResolvedLanguage()
|
||||
const locale = LOCALE_MAP[lang] ?? 'zh-CN'
|
||||
|
||||
for (const skillName of skillNames) {
|
||||
const skillDir = join(skillsDir, skillName)
|
||||
if (!(await needsUpdate(skillDir, skillName, locale))) continue
|
||||
const cacheDir = getSkillCacheDir()
|
||||
const skillNames = Builtin.listBuiltinSkills()
|
||||
|
||||
await mkdir(skillDir, { recursive: true })
|
||||
await extractBundledSkill(skillName, skillDir, locale)
|
||||
await writeVersionFile(skillDir, skillName, locale)
|
||||
for (const name of skillNames) {
|
||||
const skillDir = path.join(cacheDir, name)
|
||||
|
||||
const dirExists = await stat(skillDir).then(s => s.isDirectory()).catch(() => false)
|
||||
|
||||
if (dirExists) {
|
||||
const updateNeeded = await needsUpdate(skillDir, name, locale)
|
||||
if (!updateNeeded) continue
|
||||
|
||||
try {
|
||||
await rm(skillDir, { recursive: true, force: true })
|
||||
} catch {
|
||||
// Continue with copy over existing files
|
||||
}
|
||||
}
|
||||
|
||||
await Builtin.extractBundledSkill(name, skillDir, locale)
|
||||
await writeVersionFile(skillDir, name, locale)
|
||||
|
||||
const skillFiles = Builtin.listSkillFiles(name, locale)
|
||||
const builtinVersion = Builtin.getBuiltinSkillVersion(name)
|
||||
console.log(` [review] initialized skill "${name}" (${locale}, ${skillFiles.length} files, v${builtinVersion?.slice(0, 7)})`)
|
||||
}
|
||||
}
|
||||
|
||||
export function getBuiltinSkillsDir(): string {
|
||||
return getReviewSkillsDir()
|
||||
return getSkillCacheDir()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
/**
|
||||
* CoStrict Review Module
|
||||
*
|
||||
* Provides builtin review skills that are extracted to disk at runtime
|
||||
* and discovered by the standard skill scanner.
|
||||
* Provides builtin review skills and agents that are embedded
|
||||
* in the binary and extracted to cache on first run.
|
||||
*/
|
||||
|
||||
export * as SkillBuiltin from './skill/builtin.js'
|
||||
export * as Extension from './extension.js'
|
||||
export * as SkillBuiltin from './skill/builtin.js'
|
||||
export {
|
||||
REVIEW_AGENTS,
|
||||
AGENT_VERSIONS,
|
||||
PRIMARY_REVIEW_AGENT,
|
||||
SUB_REVIEW_AGENT,
|
||||
} from './agent/builtin.js'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { feature } from 'bun:bundle'
|
||||
import { shouldAutoEnableClaudeInChrome } from 'src/utils/claudeInChrome/setup.js'
|
||||
import { Extension as ReviewExtension } from 'src/costrict/review/index.js'
|
||||
import { initializeBuiltinSkills } from 'src/costrict/review/extension.js'
|
||||
import { registerBatchSkill } from './batch.js'
|
||||
import { registerClaudeInChromeSkill } from './claudeInChrome.js'
|
||||
import { registerDebugSkill } from './debug.js'
|
||||
|
|
@ -30,8 +30,8 @@ import { registerTddSkill } from 'src/costrict/skills/tdd.js'
|
|||
* 3. Import and call that function here
|
||||
*/
|
||||
export function initBundledSkills(): void {
|
||||
// Extract review skills to disk for standard scanner discovery
|
||||
ReviewExtension.initializeBuiltinSkills().catch(() => {})
|
||||
// Initialize builtin review skills (extract to cache if needed)
|
||||
initializeBuiltinSkills().catch(() => {})
|
||||
|
||||
registerUpdateConfigSkill()
|
||||
registerProjectWikiSkill()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user