fix: keep feature markers in GStack state

This commit is contained in:
Simon Altit
2026-08-31 21:02:34 +00:00
committed by Garry Tan
parent 96ac9bbfef
commit 6a14a387d0
2 changed files with 46 additions and 5 deletions
+7 -5
View File
@@ -362,14 +362,16 @@ if [ -n "$_UPD" ]; then
The update-check output above applies. If it shows \`UPGRADE_AVAILABLE <old> <new>\`: read \`$_ROOT_DIR/gstack-upgrade/SKILL.md\` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If it shows \`JUST_UPGRADED <from> <to>\`: print "Running gstack v{to} (just updated!)". If \`SPAWNED_SESSION\` is true, skip feature discovery. After upgrade prompts, continue the workflow.
EOI
fi
# Feature discovery (one prompt per session, marker-gated).
if [ ! -f "$_ROOT_DIR/.feature-prompted-continuous-checkpoint" ]; then
# Feature discovery (one prompt per session, marker-gated). These are
# machine-local UX acknowledgements, so keep them in GSTACK_HOME rather than
# beside an install path that may resolve through a project-local symlink.
if [ ! -f "$_GH/.feature-prompted-continuous-checkpoint" ]; then
_emit_block feature-checkpoint <<EOI
Feature discovery: AskUserQuestion for Continuous checkpoint auto-commits. If accepted, run \`$_BIN/gstack-config set checkpoint_mode continuous\`. Always run: \`touch "$_ROOT_DIR/.feature-prompted-continuous-checkpoint"\`.
Feature discovery: AskUserQuestion for Continuous checkpoint auto-commits. If accepted, run \`$_BIN/gstack-config set checkpoint_mode continuous\`. Always run: \`touch "$_GH/.feature-prompted-continuous-checkpoint"\`.
EOI
elif [ ! -f "$_ROOT_DIR/.feature-prompted-model-overlay" ]; then
elif [ ! -f "$_GH/.feature-prompted-model-overlay" ]; then
_emit_block feature-overlay <<EOI
Feature discovery: inform "Model overlays are active. MODEL_OVERLAY shows the patch." Always run: \`touch "$_ROOT_DIR/.feature-prompted-model-overlay"\`.
Feature discovery: inform "Model overlays are active. MODEL_OVERLAY shows the patch." Always run: \`touch "$_GH/.feature-prompted-model-overlay"\`.
EOI
fi
+39
View File
@@ -302,6 +302,45 @@ describe('gstack-skill-start behavior', () => {
}
});
test('feature acknowledgement markers stay in GSTACK_HOME through a project-local bin symlink', () => {
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-ss-project-'));
const projectSkillRoot = path.join(projectRoot, '.agents', 'skills', 'gstack');
const freshGh = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-ss-feature-state-'));
fs.mkdirSync(projectSkillRoot, { recursive: true });
fs.symlinkSync(path.join(ROOT, 'bin'), path.join(projectSkillRoot, 'bin'), 'dir');
fs.writeFileSync(path.join(freshGh, 'config.yaml'), 'update_check: false\n');
const localStart = path.join(projectSkillRoot, 'bin', 'gstack-skill-start');
const env = { PATH: process.env.PATH!, HOME: tmpHome, GSTACK_HOME: freshGh };
try {
const checkpoint = execFileSync(localStart, ['--skill', 'testskill'], {
encoding: 'utf-8',
cwd: projectRoot,
env,
});
expect(checkpoint).toContain(
`touch "${path.join(freshGh, '.feature-prompted-continuous-checkpoint')}"`,
);
expect(checkpoint).not.toContain(
path.join(projectSkillRoot, '.feature-prompted-continuous-checkpoint'),
);
fs.writeFileSync(path.join(freshGh, '.feature-prompted-continuous-checkpoint'), '');
const overlay = execFileSync(localStart, ['--skill', 'testskill'], {
encoding: 'utf-8',
cwd: projectRoot,
env,
});
expect(overlay).toContain(
`touch "${path.join(freshGh, '.feature-prompted-model-overlay')}"`,
);
expect(overlay).not.toContain(path.join(projectSkillRoot, '.feature-prompted-model-overlay'));
} finally {
fs.rmSync(projectRoot, { recursive: true, force: true });
fs.rmSync(freshGh, { recursive: true, force: true });
}
});
test('MODEL_OVERLAY echoes the --model argument', () => {
const out = runStart(['--model', 'opus']);
expect(out).toMatch(/^MODEL_OVERLAY: opus$/m);