mirror of
https://github.com/garrytan/gstack.git
synced 2026-07-06 08:07:53 +02:00
feat: QA restructure, browser ref staleness, eval efficiency metrics (v0.4.0) (#83)
* feat: browser ref staleness detection via async count() validation resolveRef() now checks element count to detect stale refs after page mutations (e.g. SPA navigation). RefEntry stores role+name metadata for better diagnostics. 3 new snapshot tests for staleness detection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: qa-only skill, qa fix loop, plan-to-QA artifact flow Add /qa-only (report-only, Edit tool blocked), restructure /qa with find-fix-verify cycle, add {{QA_METHODOLOGY}} DRY placeholder for shared methodology. /plan-eng-review now writes test-plan artifacts to ~/.gstack/projects/<slug>/ for QA consumption. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: eval efficiency metrics — turns, duration, commentary across all surfaces Add generateCommentary() for natural-language delta interpretation, per-test turns/duration in comparison and summary output, judgePassed unit tests, 3 new E2E tests (qa-only, qa fix loop, plan artifact). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: bump version and changelog (v0.4.0) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update ARCHITECTURE, BROWSER, CONTRIBUTING, README for v0.4.0 - ARCHITECTURE: add ref staleness detection section, update RefEntry type - BROWSER: add ref staleness paragraph to snapshot system docs - CONTRIBUTING: update eval tool descriptions with commentary feature - README: fix missing qa-only in project-local uninstall command Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add user-facing benefit descriptions to v0.4.0 changelog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,20 @@ describe('SKILL.md command validation', () => {
|
||||
const result = validateSkill(qaSkill);
|
||||
expect(result.snapshotFlagErrors).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('all $B commands in qa-only/SKILL.md are valid browse commands', () => {
|
||||
const qaOnlySkill = path.join(ROOT, 'qa-only', 'SKILL.md');
|
||||
if (!fs.existsSync(qaOnlySkill)) return;
|
||||
const result = validateSkill(qaOnlySkill);
|
||||
expect(result.invalid).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('all snapshot flags in qa-only/SKILL.md are valid', () => {
|
||||
const qaOnlySkill = path.join(ROOT, 'qa-only', 'SKILL.md');
|
||||
if (!fs.existsSync(qaOnlySkill)) return;
|
||||
const result = validateSkill(qaOnlySkill);
|
||||
expect(result.snapshotFlagErrors).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Command registry consistency', () => {
|
||||
@@ -157,6 +171,7 @@ describe('Generated SKILL.md freshness', () => {
|
||||
describe('Update check preamble', () => {
|
||||
const skillsWithUpdateCheck = [
|
||||
'SKILL.md', 'browse/SKILL.md', 'qa/SKILL.md',
|
||||
'qa-only/SKILL.md',
|
||||
'setup-browser-cookies/SKILL.md',
|
||||
'ship/SKILL.md', 'review/SKILL.md',
|
||||
'plan-ceo-review/SKILL.md', 'plan-eng-review/SKILL.md',
|
||||
@@ -261,7 +276,7 @@ describe('Cross-skill path consistency', () => {
|
||||
describe('QA skill structure validation', () => {
|
||||
const qaContent = fs.readFileSync(path.join(ROOT, 'qa', 'SKILL.md'), 'utf-8');
|
||||
|
||||
test('qa/SKILL.md has all 6 phases', () => {
|
||||
test('qa/SKILL.md has all 11 phases', () => {
|
||||
const phases = [
|
||||
'Phase 1', 'Initialize',
|
||||
'Phase 2', 'Authenticate',
|
||||
@@ -269,6 +284,11 @@ describe('QA skill structure validation', () => {
|
||||
'Phase 4', 'Explore',
|
||||
'Phase 5', 'Document',
|
||||
'Phase 6', 'Wrap Up',
|
||||
'Phase 7', 'Triage',
|
||||
'Phase 8', 'Fix Loop',
|
||||
'Phase 9', 'Final QA',
|
||||
'Phase 10', 'Report',
|
||||
'Phase 11', 'TODOS',
|
||||
];
|
||||
for (const phase of phases) {
|
||||
expect(qaContent).toContain(phase);
|
||||
@@ -291,6 +311,13 @@ describe('QA skill structure validation', () => {
|
||||
expect(qaContent).toContain('--regression');
|
||||
});
|
||||
|
||||
test('has all three tiers defined', () => {
|
||||
const tiers = ['Quick', 'Standard', 'Exhaustive'];
|
||||
for (const tier of tiers) {
|
||||
expect(qaContent).toContain(tier);
|
||||
}
|
||||
});
|
||||
|
||||
test('health score weights sum to 100%', () => {
|
||||
const weights = extractWeightsFromTable(qaContent);
|
||||
expect(weights.size).toBeGreaterThan(0);
|
||||
|
||||
Reference in New Issue
Block a user