mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-09 06:28:59 +02:00
fix: align feature marker seeding with GStack state
Wave-amended: seeding relocation re-applied to the composite action (v1.77 moved CI seeding out of the inline workflow steps the original commit edited); wiring tripwire re-pointed accordingly; stale marker comment updated
This commit is contained in:
@@ -70,11 +70,9 @@ runs:
|
||||
"$HOME/.gstack/.telemetry-prompted" \
|
||||
"$HOME/.gstack/.proactive-prompted" \
|
||||
"$HOME/.gstack/.completeness-intro-seen" \
|
||||
"$HOME/.gstack/.plan-tune-nudge-shown"
|
||||
# These two resolve through the gstack root symlink into $REPO —
|
||||
# untracked scratch in the CI checkout, exactly where the preamble looks.
|
||||
touch "$SKILLS_DIR/gstack/.feature-prompted-continuous-checkpoint" \
|
||||
"$SKILLS_DIR/gstack/.feature-prompted-model-overlay"
|
||||
"$HOME/.gstack/.plan-tune-nudge-shown" \
|
||||
"$HOME/.gstack/.feature-prompted-continuous-checkpoint" \
|
||||
"$HOME/.gstack/.feature-prompted-model-overlay"
|
||||
echo "--- registry under $SKILLS_DIR ---"
|
||||
ls -la "$SKILLS_DIR/gstack"
|
||||
# ── Fail-fast verification ──────────────────────────────────────────
|
||||
|
||||
@@ -321,6 +321,7 @@ describe('gstack-skill-start behavior', () => {
|
||||
expect(checkpoint).toContain(
|
||||
`touch "${path.join(freshGh, '.feature-prompted-continuous-checkpoint')}"`,
|
||||
);
|
||||
expect(checkpoint).not.toContain('GSTACK_INSTRUCTION_BEGIN: feature-overlay');
|
||||
expect(checkpoint).not.toContain(
|
||||
path.join(projectSkillRoot, '.feature-prompted-continuous-checkpoint'),
|
||||
);
|
||||
@@ -334,7 +335,19 @@ describe('gstack-skill-start behavior', () => {
|
||||
expect(overlay).toContain(
|
||||
`touch "${path.join(freshGh, '.feature-prompted-model-overlay')}"`,
|
||||
);
|
||||
expect(overlay).not.toContain('GSTACK_INSTRUCTION_BEGIN: feature-checkpoint');
|
||||
expect(overlay).not.toContain(path.join(projectSkillRoot, '.feature-prompted-model-overlay'));
|
||||
|
||||
fs.writeFileSync(path.join(freshGh, '.feature-prompted-model-overlay'), '');
|
||||
const acknowledged = execFileSync(localStart, ['--skill', 'testskill'], {
|
||||
encoding: 'utf-8',
|
||||
cwd: projectRoot,
|
||||
env,
|
||||
});
|
||||
expect(acknowledged).not.toContain('GSTACK_INSTRUCTION_BEGIN: feature-checkpoint');
|
||||
expect(acknowledged).not.toContain('GSTACK_INSTRUCTION_BEGIN: feature-overlay');
|
||||
expect(acknowledged).not.toContain('.feature-prompted-continuous-checkpoint');
|
||||
expect(acknowledged).not.toContain('.feature-prompted-model-overlay');
|
||||
} finally {
|
||||
fs.rmSync(projectRoot, { recursive: true, force: true });
|
||||
fs.rmSync(freshGh, { recursive: true, force: true });
|
||||
|
||||
@@ -324,7 +324,15 @@ if (evalsEnabled) {
|
||||
fs.mkdirSync(gstackDir, { recursive: true });
|
||||
// Marker list kept at parity with hermetic-env.ts's child-GSTACK_HOME seed
|
||||
// (the canonical set for the emission layer's gates).
|
||||
for (const f of ['.activated', '.completeness-intro-seen', '.telemetry-prompted', '.proactive-prompted', '.first-loop-tip-shown']) {
|
||||
for (const f of [
|
||||
'.activated',
|
||||
'.completeness-intro-seen',
|
||||
'.telemetry-prompted',
|
||||
'.proactive-prompted',
|
||||
'.first-loop-tip-shown',
|
||||
'.feature-prompted-continuous-checkpoint',
|
||||
'.feature-prompted-model-overlay',
|
||||
]) {
|
||||
const p = path.join(gstackDir, f);
|
||||
if (!fs.existsSync(p)) fs.writeFileSync(p, '');
|
||||
}
|
||||
|
||||
@@ -217,7 +217,15 @@ export function getHermeticDirs(): HermeticDirs {
|
||||
// children — without these, the emission layer fires lake-intro/telemetry
|
||||
// prompts that burn turns and can stall PTY tests waiting on an answer.
|
||||
// Tests that exercise onboarding itself override GSTACK_HOME per-test.
|
||||
for (const f of ['.activated', '.completeness-intro-seen', '.telemetry-prompted', '.proactive-prompted', '.first-loop-tip-shown']) {
|
||||
for (const f of [
|
||||
'.activated',
|
||||
'.completeness-intro-seen',
|
||||
'.telemetry-prompted',
|
||||
'.proactive-prompted',
|
||||
'.first-loop-tip-shown',
|
||||
'.feature-prompted-continuous-checkpoint',
|
||||
'.feature-prompted-model-overlay',
|
||||
]) {
|
||||
fs.writeFileSync(path.join(gstackHome, f), '');
|
||||
}
|
||||
// The privacy stop-gate is config-keyed, not marker-keyed: on machines
|
||||
|
||||
@@ -60,6 +60,34 @@ describe('hermetic wiring tripwire', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('feature prompt acknowledgements are seeded in GSTACK_HOME everywhere', () => {
|
||||
const markers = [
|
||||
'.feature-prompted-continuous-checkpoint',
|
||||
'.feature-prompted-model-overlay',
|
||||
];
|
||||
// CI seeding lives in the composite action (v1.77 moved it out of the
|
||||
// inline workflow steps) — the workflows call the action, so one seeding
|
||||
// site covers every lane.
|
||||
const sources: Array<[string, number]> = [
|
||||
['test/helpers/hermetic-env.ts', 1],
|
||||
['test/helpers/e2e-helpers.ts', 1],
|
||||
['.github/actions/register-gstack-skills/action.yml', 1],
|
||||
];
|
||||
|
||||
for (const [rel, expectedCount] of sources) {
|
||||
const src = read(rel);
|
||||
for (const marker of markers) {
|
||||
expect(src.split(marker).length - 1, `${rel}: ${marker}`).toBe(expectedCount);
|
||||
}
|
||||
}
|
||||
|
||||
for (const rel of ['.github/actions/register-gstack-skills/action.yml']) {
|
||||
const src = read(rel);
|
||||
expect(src).not.toContain('$SKILLS_DIR/gstack/.feature-prompted-');
|
||||
for (const marker of markers) expect(src).toContain(`$HOME/.gstack/${marker}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('claude runners gate --strict-mcp-config on isHermeticEnabled()', () => {
|
||||
// Zero MCP servers for hermetic children; EVALS_HERMETIC=0 must restore
|
||||
// operator MCP along with the operator env (the flag may not be
|
||||
|
||||
@@ -196,7 +196,7 @@ describe('two-class referenced-paths (ENG-OV7)', () => {
|
||||
const missing: string[] = [];
|
||||
for (const { fromSkill, skillName, rel } of collectRefs()) {
|
||||
if (skillName !== 'gstack') continue; // class 1
|
||||
if (rel.startsWith('.')) continue; // runtime state markers (.feature-prompted-*, .git)
|
||||
if (rel.startsWith('.')) continue; // runtime state (.git; feature markers now live in ~/.gstack — #2728)
|
||||
if (BUILT_ARTIFACT_ALLOWLIST.some((a) => rel === a || rel.startsWith(a))) continue;
|
||||
if (KNOWN_BROKEN_CLASS2[rel]) continue;
|
||||
if (!fs.existsSync(path.join(ROOT, rel))) {
|
||||
|
||||
Reference in New Issue
Block a user