mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-04 20:26:38 +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:
co-authored by
Claude Opus 4.6
parent
bb46ca6b21
commit
f3ee0ee28a
@@ -61,7 +61,7 @@ export async function handleReadCommand(
|
||||
case 'html': {
|
||||
const selector = args[0];
|
||||
if (selector) {
|
||||
const resolved = bm.resolveRef(selector);
|
||||
const resolved = await bm.resolveRef(selector);
|
||||
if ('locator' in resolved) {
|
||||
return await resolved.locator.innerHTML({ timeout: 5000 });
|
||||
}
|
||||
@@ -135,7 +135,7 @@ export async function handleReadCommand(
|
||||
case 'css': {
|
||||
const [selector, property] = args;
|
||||
if (!selector || !property) throw new Error('Usage: browse css <selector> <property>');
|
||||
const resolved = bm.resolveRef(selector);
|
||||
const resolved = await bm.resolveRef(selector);
|
||||
if ('locator' in resolved) {
|
||||
const value = await resolved.locator.evaluate(
|
||||
(el, prop) => getComputedStyle(el).getPropertyValue(prop),
|
||||
@@ -157,7 +157,7 @@ export async function handleReadCommand(
|
||||
case 'attrs': {
|
||||
const selector = args[0];
|
||||
if (!selector) throw new Error('Usage: browse attrs <selector>');
|
||||
const resolved = bm.resolveRef(selector);
|
||||
const resolved = await bm.resolveRef(selector);
|
||||
if ('locator' in resolved) {
|
||||
const attrs = await resolved.locator.evaluate((el) => {
|
||||
const result: Record<string, string> = {};
|
||||
@@ -221,7 +221,7 @@ export async function handleReadCommand(
|
||||
const selector = args[1];
|
||||
if (!property || !selector) throw new Error('Usage: browse is <property> <selector>\nProperties: visible, hidden, enabled, disabled, checked, editable, focused');
|
||||
|
||||
const resolved = bm.resolveRef(selector);
|
||||
const resolved = await bm.resolveRef(selector);
|
||||
let locator;
|
||||
if ('locator' in resolved) {
|
||||
locator = resolved.locator;
|
||||
|
||||
Reference in New Issue
Block a user