mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-09 06:28:59 +02:00
fix(render): section refs point at the FINAL render dir, never the tmp swap dir (#2692)
gen-skill-docs bakes its --out-dir into rendered CONTENT (rewriteSectionBase), and both swap-in callers (setup, gstack-config gbrain-refresh) render into claude.tmp.<pid> before the #2569 atomic rename — so every rendered skill carried ~9 dead section Read paths that pointed at a directory the swap had just deleted. New --link-root flag names the final serving dir (defaults to --out-dir for direct-render callers: bin/dev-setup, dev-skill.ts, mkdtemp tests — full caller audit in the wave notes); the rewrite now uses a replacement callback so a $-bearing configured path can't expand as $& in a replacement string. The swap logic itself stays byte-identical. Tests pin the generator contract (tmp out-dir files reference the final dir, $-bearing path included) and both callers' wiring. Fixes #2692 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e2d6cb570f
commit
7ed5e87bba
@@ -168,6 +168,23 @@ const OUT_DIR: string | null = (() => {
|
||||
return path.resolve(val);
|
||||
})();
|
||||
|
||||
// #2692: callers that render into a TMP dir and atomically swap it into place
|
||||
// (bin/gstack-config gbrain-refresh, setup — the #2569 pattern) must pass the
|
||||
// FINAL directory here, or rewriteSectionBase bakes the tmp path
|
||||
// (…/render/claude.tmp.<pid>/…) into the rendered CONTENT and every section
|
||||
// Read dies after the swap. Defaults to OUT_DIR for direct-render callers
|
||||
// (bin/dev-setup, scripts/dev-skill.ts, mkdtemp tests), where out-dir IS the
|
||||
// serving path.
|
||||
const LINK_ROOT_ARG = process.argv.find(a => a.startsWith('--link-root'));
|
||||
const LINK_ROOT: string | null = (() => {
|
||||
if (!LINK_ROOT_ARG) return OUT_DIR;
|
||||
const val = LINK_ROOT_ARG.includes('=')
|
||||
? LINK_ROOT_ARG.split('=')[1]
|
||||
: process.argv[process.argv.indexOf(LINK_ROOT_ARG) + 1];
|
||||
if (!val) throw new Error('--link-root requires a directory path');
|
||||
return path.resolve(val);
|
||||
})();
|
||||
|
||||
/**
|
||||
* When rendering to an out-dir, repoint the literal section-base path at the
|
||||
* out-dir so section Reads resolve to the rendered copy, not the global install.
|
||||
@@ -176,10 +193,12 @@ const OUT_DIR: string | null = (() => {
|
||||
* install, which still works). No-op when --out-dir is unset.
|
||||
*/
|
||||
function rewriteSectionBase(content: string): string {
|
||||
if (!OUT_DIR) return content;
|
||||
if (!LINK_ROOT) return content;
|
||||
// Replacement CALLBACK, not a template string: `$` sequences in a
|
||||
// configured path are special in JS replacement strings ($&, $', $1…).
|
||||
return content.replace(
|
||||
/~\/\.claude\/skills\/gstack\/([^\s)`"'*]+\/sections\/)/g,
|
||||
`${OUT_DIR}/$1`,
|
||||
(_m, p1: string) => `${LINK_ROOT}/${p1}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user