mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-18 09:06:53 +03:00
Add concept world catalog and review workflow
AI-assisted: prepared by Codex at Paul's request.
This commit is contained in:
+42
-4
@@ -440,6 +440,38 @@ function copyDirSync(src, dest) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an existing directory match a generated source without removing the
|
||||
* destination root. Provider skill roots can be watched by the running agent;
|
||||
* replacing that root fails on some platforms and can invalidate the live
|
||||
* skill path mid-session.
|
||||
*/
|
||||
function mirrorDirContentsSync(src, dest) {
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
const sourceEntries = new Map(
|
||||
fs.readdirSync(src, { withFileTypes: true }).map(entry => [entry.name, entry]),
|
||||
);
|
||||
|
||||
for (const destEntry of fs.readdirSync(dest, { withFileTypes: true })) {
|
||||
if (!sourceEntries.has(destEntry.name)) {
|
||||
fs.rmSync(path.join(dest, destEntry.name), { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
for (const entry of sourceEntries.values()) {
|
||||
const srcPath = path.join(src, entry.name);
|
||||
const destPath = path.join(dest, entry.name);
|
||||
const destStat = fs.existsSync(destPath) ? fs.lstatSync(destPath) : null;
|
||||
if (entry.isDirectory()) {
|
||||
if (destStat && !destStat.isDirectory()) fs.rmSync(destPath, { recursive: true, force: true });
|
||||
mirrorDirContentsSync(srcPath, destPath);
|
||||
} else {
|
||||
if (destStat?.isDirectory()) fs.rmSync(destPath, { recursive: true, force: true });
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function syncRootHookManifests(rootDir) {
|
||||
const synced = [];
|
||||
for (const config of Object.values(PROVIDERS)) {
|
||||
@@ -688,11 +720,17 @@ async function build() {
|
||||
|
||||
if (fs.existsSync(skillsSrc)) {
|
||||
// Preserve legacy per-project script artifacts (e.g. live-mode config.json)
|
||||
// across the rm + recopy. The build intentionally doesn't ship them,
|
||||
// so without this the sync destroys local state on every rebuild.
|
||||
// while replacing only skills generated by this build. Removing the
|
||||
// whole provider skills directory can erase unrelated repo-local skills,
|
||||
// and watched directories such as `.agents/skills` may reject the parent
|
||||
// removal while Codex is using them.
|
||||
const stashed = stashPerProjectArtifacts(skillsDest);
|
||||
if (fs.existsSync(skillsDest)) fs.rmSync(skillsDest, { recursive: true });
|
||||
copyDirSync(skillsSrc, skillsDest);
|
||||
fs.mkdirSync(skillsDest, { recursive: true });
|
||||
for (const entry of fs.readdirSync(skillsSrc, { withFileTypes: true })) {
|
||||
const generatedDest = path.join(skillsDest, entry.name);
|
||||
if (entry.isDirectory()) mirrorDirContentsSync(path.join(skillsSrc, entry.name), generatedDest);
|
||||
else fs.copyFileSync(path.join(skillsSrc, entry.name), generatedDest);
|
||||
}
|
||||
restorePerProjectArtifacts(skillsDest, stashed);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user