mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-08 17:58:13 +01:00
fix(proactive): gstack-skill-start falls back to core, not true, when gstack-config is missing
The PROACTIVE status line's fallback literal still said true (= all) after the default moved to core. Found by /ship's coverage audit; the regression test fails at the previous head and passes at main. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
b11514270a
commit
9e22d7f326
2 files changed
+80
-1
No files matched your search
@@ -132,7 +132,7 @@ find "$_GH/sessions" -mmin +120 -type f -exec rm {} + 2>/dev/null || true
|
||||
}
|
||||
_SESSIONS=$(find "$_GH/sessions" -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
_PROACTIVE=$("$_BIN/gstack-config" get proactive 2>/dev/null || echo "true")
|
||||
_PROACTIVE=$("$_BIN/gstack-config" get proactive 2>/dev/null || echo "core")
|
||||
_PROACTIVE_PROMPTED=$([ -f "$_GH/.proactive-prompted" ] && echo "yes" || echo "no")
|
||||
# Branch name is embedded in concatenated JSON below; strip anything outside
|
||||
# the gstack-slug BRANCH alphabet so a hostile ref name can't forge fields.
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* The PROACTIVE STATUS line (GSTA-93 fix 12, proactive core default): every
|
||||
* skill reads `PROACTIVE:` from bin/gstack-skill-start, which asks
|
||||
* bin/gstack-config and falls back to a literal when the config binary is
|
||||
* missing. The default moved from `true` to `core`.
|
||||
*
|
||||
* A fallback that still says `true` means a broken install (no gstack-config
|
||||
* beside the script) auto-invokes every skill while the documented default is
|
||||
* the core four.
|
||||
*
|
||||
* Value: protects=a skill run whose bin has no gstack-config reports the same
|
||||
* proactive mode as the config default; fails_when=lookup_default moves (true
|
||||
* to core) without the skill-start fallback literal following; why_new=no test
|
||||
* ran skill-start without gstack-config beside it; seam=none (the script is
|
||||
* copied next to an empty bin, the OV4 sanitize test's pattern); no_claim=how
|
||||
* the model applies the value (prose, not executed here)
|
||||
*
|
||||
* Regression proof — fails at HEAD: yes · passes at base: yes · passes after fix: yes
|
||||
*/
|
||||
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
import { runBin } from './helpers/run-bin';
|
||||
|
||||
const ROOT = path.resolve(import.meta.dir, '..');
|
||||
const BIN = path.join(ROOT, 'bin');
|
||||
|
||||
let tmpHome: string;
|
||||
|
||||
beforeAll(() => {
|
||||
tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-proactive-ss-home-'));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
fs.rmSync(tmpHome, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
function freshState(config: string): string {
|
||||
const state = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-proactive-ss-state-'));
|
||||
fs.writeFileSync(path.join(state, 'config.yaml'), config);
|
||||
return state;
|
||||
}
|
||||
|
||||
function runStart(script: string, state: string): string {
|
||||
const r = runBin(script, ['--skill', 'testskill'], {
|
||||
cwd: tmpHome,
|
||||
timeoutMs: 30_000,
|
||||
env: {
|
||||
PATH: process.env.PATH,
|
||||
HOME: tmpHome,
|
||||
GSTACK_HOME: state,
|
||||
GSTACK_STATE_DIR: state,
|
||||
GSTACK_LEASE_DIR: path.join(state, 'leases'),
|
||||
},
|
||||
});
|
||||
expect(r.status, r.stderr).toBe(0);
|
||||
return r.stdout;
|
||||
}
|
||||
|
||||
const proactiveLine = (out: string) => out.match(/^PROACTIVE: (.*)$/m)?.[1];
|
||||
|
||||
describe('gstack-skill-start PROACTIVE fallback', () => {
|
||||
test('regression: with no gstack-config beside it, the fallback reports the config default, not a stale literal', () => {
|
||||
const fakeBin = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-proactive-ss-bin-'));
|
||||
const state = freshState('update_check: false\n');
|
||||
try {
|
||||
for (const f of ['gstack-skill-start', 'gstack-state-root.sh']) fs.copyFileSync(path.join(BIN, f), path.join(fakeBin, f));
|
||||
fs.chmodSync(path.join(fakeBin, 'gstack-skill-start'), 0o755);
|
||||
const configDefault = runBin(path.join(BIN, 'gstack-config'), ['get', 'proactive'], { gstackHome: state, cwd: ROOT, trim: true }).stdout;
|
||||
expect(configDefault).not.toBe('');
|
||||
expect(proactiveLine(runStart(path.join(fakeBin, 'gstack-skill-start'), state))).toBe(configDefault);
|
||||
} finally {
|
||||
fs.rmSync(fakeBin, { recursive: true, force: true });
|
||||
fs.rmSync(state, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user