H1: detectVibium reads stderr too, extracts semver
- Many Go CLIs (including some Vibium versions) write --version to stderr.
detectVibium used to read only stdout and silently report 'unknown',
polluting the init log with "vibium unknown (already installed)".
- Fix: read both streams, prefer stdout, extract bare semver via regex
so output is consistent regardless of where the binary printed it.
- Tests: 5 new regression tests covering stderr fallback, stdout
preference, verbose-format extraction, prerelease tags, fallback to
first whitespace token.
- Note: result.version is now bare semver (26.3.18) not v-prefixed.
Two pre-existing tests updated to match the new contract.
H2: instructions_in_html_comment dead-code regex
- TreeWalker(SHOW_COMMENT).textContent yields the inner text without
the <!-- --> delimiters, so the pattern that requires the literal
`<!--` prefix could never fire. Eval tc009 was passing only by
accident (ignore_previous_instructions fired on the same fixture).
- Fix: re-wrap each comment node in `<!-- ... -->` before adding to
the hidden bucket. Pattern can now actually match.
- Tests: 2 new regression tests asserting wrapped form fires AND
unwrapped form does NOT fire (the bug condition).
H4: e2e-flow-verifier frontmatter regression — INVALID FINDING
- Verified against `git show main:` — the skill always had minimal
frontmatter on main (just name + description + user-invocable: true)
and has no evals/, schemas/, or scripts/ directories. It is a
user-invocable runbook-style skill, not trust-tier-3 validated.
No metadata to restore. Marked closed-as-invalid.
H6: log-before-spawn for the 3-minute Vibium install
- spawnSync(npm install -g vibium) blocks the event loop for up to
3 minutes on a cold cache while Chrome for Testing downloads. The
user saw zero output and would Ctrl-C thinking init hung.
- Fix: pre-flight detect call (5s timeout) short-circuits when vibium
is already installed (the common case, no banner). When the install
is actually about to run, log a clear "this can take 1-3 minutes,
downloads Chrome for Testing lazily" message BEFORE the spawn.
H7: scoped scripts/package.json survives npm pack — VERIFIED
- `npm pack --dry-run` confirms both
.claude/skills/qe-browser/scripts/package.json (225B) AND
assets/skills/qe-browser/scripts/package.json (225B)
are included in the published tarball. The CommonJS override that
keeps the helper scripts loadable from an ESM project root will
survive `npm install` after publication. No fix needed.
H8: eval yaml uses unsupported runner fields
- The structured assertion fields I invented (exit_code, json_fields,
severity_at_least, candidate_count_at_least) are NOT understood by
src/validation/parallel-eval-runner.ts which expects must_contain
keyword matching. The yaml as written is unrunnable.
- Honest fix: relabel evals/qe-browser.yaml as `status: design-spec`
with a HONESTY NOTE explaining it's a specification, not a runnable
eval. Two paths to make it runnable documented (extend runner OR
rewrite as must_contain).
- Parallel artifact: scripts/smoke-test.sh — a runnable bash smoke
test against the same pinned httpbin.org fixtures. THIS is the
script that gates PR-reopen per ADR-091 Phase 3.
Bonus from B2/H5 already in Phase 1:
- assert.js now uses ?? instead of || for the `expected` field
Verification:
- 50/50 qe-browser tests pass (was 36 in initial PR; +14 regressions)
- 392/392 init tests pass (was 387; +5 from H1)
- npm run build: clean
- npm pack --dry-run: scoped package.json confirmed in tarball
- eslint on all touched source files: clean
- bash -n smoke-test.sh: syntax OK
Phase 3 (real Vibium smoke test) still gating PR reopen per ADR-091.
Branch intentionally not pushed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a new AQE-owned browser automation skill layered over Vibium
(WebDriver BiDi, single 10MB Go binary) and migrates 11 browser-using QE
skills to use it instead of raw Playwright/Puppeteer.
qe-browser ships five helper scripts that add QE primitives Vibium doesn't
cover on its own: typed assertions (16 check kinds), batch execution,
pixel-diff against stored baselines, prompt-injection scanning, and
semantic intent scoring ported from gsd-browser (MIT/Apache). Each script
emits a structured JSON envelope matching schemas/output.json so hooks
and CI gates can parse results without stdout grep.
Vibium installs automatically during `aqe init` via a new graceful
browser-engine installer that shells out to `npm install -g vibium` and
reports `already-installed`, `installed`, `install-failed`, or
`npm-unavailable` without ever failing init.
Skills migrated to reference qe-browser:
a11y-ally, e2e-flow-verifier, qe-visual-accessibility,
security-visual-testing, visual-testing-advanced, testability-scoring,
compatibility-testing, accessibility-testing, localization-testing,
observability-testing-patterns, enterprise-integration-testing.
Ships 36 new unit tests (browser-engine-installer, assert, intent-score,
check-injection) with dependency-injected spawners to avoid touching real
processes. All 387 existing init tests still pass.
Eval harness uses pinned public fixtures (httpbin.org, Vibium docs at a
pinned tag) plus a local static server that wraps this repo's own skill
docs, per the "no synthetic fixtures" rule.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses the v3.9.1–v3.9.4 init regression series by building the
verification layer that #401's post-mortem identified as structurally
missing. The load-bearing changes are the real-public-repo corpus, the
--json contract, and the restructured error handling in phase 06 that
stops lying about success when a non-critical phase fails.
What landed
-----------
* `aqe init --json` — structured InitResult output with schema version 1,
stricter exit code semantics (exit 1 on any step.status='error', not
just on critical failures). Stable contract for the gate and other CI
consumers. See InitJsonOutput in src/cli/handlers/init-handler.ts.
* Phase 06 no longer swallows errors as `{status:'skipped',entries:0}`.
Exceptions now propagate to BasePhase.execute() and surface as real
step errors in result.steps[]. Fixed a resource leak where kgService
and memory handles were leaked on the old throw path — now always
released via try/finally.
* `tests/fixtures/init-corpus/` — 4 pinned real public repo fixtures:
- tiny-ts (developit/mitt@b240473)
- mid-ts (sindresorhus/p-queue@55d306b)
- multi-lang-real (ruvnet/RuView@2a05378 — contains the exact 28,745
byte / 776 line ruview_live.py that triggered the v3.9.4 hang,
sha256-pinned to detect content drift)
- self-dogfood (agentic-qe HEAD)
* 22 gate assertions per fixture (A1–A22) including per-step JSON error
inspection (A10), snapshot-based KG threshold with tolerance (A12),
skills/agents/MCP/CLAUDE.md/workers/config.yaml presence (A13–A20),
subthreshold stall detection (A21), and a second init pass that
exercises the delta-scan path of phase 06 — the actual surface that
hung in v3.9.1 ruview, never reached on a first init (A22).
* `.github/workflows/npm-publish.yml` — new pre-publish-gate job that
runs the corpus against the freshly-built tarball before publish; new
tests-on-tag-sha job that re-runs fast unit tests on release events
(replaces a buggy gh-api conditional caught by devils-advocate review).
* `.github/workflows/post-publish-canary.yml` — fires on real publishes
only (not workflow_dispatch dry runs), polls npm CDN via
`npm install --dry-run` (actual CDN edge, not just registry metadata),
runs the corpus against the published package, opens P0 issue on
failure via heredoc-based body.
* Watchdog effectiveness unit test
(tests/unit/init/phases/code-intelligence-watchdog.test.ts) — 4 cases
proving the async-stall branches of runBoundedScan work and
documenting the sync-block limitation that requires AQE_SKIP_CODE_INDEX
or (future) worker isolation.
* `.github/PULL_REQUEST_TEMPLATE.md` — single load-bearing checkbox:
every PR failure mode must have a test or tracking issue. Honor-system
today; CI enforcement tracked in #408.
* AQE_SKIP_CODE_INDEX promoted from "temporary escape hatch" to
permanent supported flag in docs, CLI help, and source comments.
Verification
------------
* `npm run typecheck` — clean
* `npx eslint` on all touched files — clean (plus fixed two pre-existing
unused-var warnings in init-handler.ts)
* `aqe security --sast` on all touched source + workflows — 0 findings
* `tests/unit/init/` — 377/377 pass
* `tests/unit/init/phases/code-intelligence-watchdog.test.ts` — 4/4 pass
* Local gate against `npm pack`'d tarball — 4/4 fixtures pass all 22
assertions including double-init delta path and sha256 regression
marker
Failure paths independently verified (F1–F5 injection tests):
* F1 wrong sha256 → A3 fires, exit 2, actionable diagnostic
* F2 absurd expectedKgEntries → A12 fires, exit 2, shows actual vs expected
* F3 expectedElapsedSec=0 → A21 fires on slow fixture, A22 fires on
double-init — same `(( elapsed > soft_cap ))` math proven in both paths
* F4 injected throw in runCodeIntelligenceScan → reproduces the exact
v3.9.3 failure shape (`success:true` at orchestrator level, phase 06
step.status='error'). A7 catches via strict exit code, A10 catches as
defense-in-depth via jq inspection. Both layers verified.
* F5 expectedSkillsInstalled=999 → A13 fires with OR-logic showing
json=84, disk=84 vs expected 999
Deferred with tracking issues
-----------------------------
* Phase 06 worker_threads isolation — #407
* PR template CI enforcement — #408
* VERIFICATION.md + release-notes matrix — #409
* Chaos workflow for pathological inputs — #410
* Mirror init-corpus tarballs to GitHub Releases — #411
What is NOT verified
--------------------
* The CI workflows have never actually executed in a real Actions run.
YAML syntactically validated via js-yaml, job dependency graph traced,
but the first real execution is the first push of this branch.
* The canary on a real publish is unexecuted. First execution is the
first real release after merge.
Refs: #401, #407, #408, #409, #410, #411
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prior to ADR-090, NativeHnswBackend wrapped @ruvector/router's
VectorDb, whose constructor unconditionally wrote a `vectors.db`
redb file to the current working directory — outside .agentic-qe/,
in a non-SQLite format, never read by anything in production
(its HNSW search returned wrong answers anyway). Users who upgrade
from a pre-#399 version will have an orphaned multi-MB file in
their project root.
`aqe init` now detects `./vectors.db` in the project root and logs
a one-time warning identifying it as stale from the @ruvector/router
era and suggesting `rm vectors.db` for cleanup.
The phase does NOT auto-delete the file. Per CLAUDE.md data
protection rules, AQE never overwrites, replaces, recreates, or
removes any .db file without explicit user confirmation. Users who
want to clean up run `rm vectors.db` themselves.
Three new unit tests in `tests/unit/init/phases/database-phase.test.ts`:
- asserts the warning fires when `./vectors.db` is present
- asserts the warning does not fire when it is absent
- asserts the phase never calls fs.unlinkSync or fs.rmSync,
regardless of whether vectors.db exists (data protection guard)
Refs #399, ADR-090.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hook commands using relative paths (node ./dist/...) or git rev-parse
broke when invoked from subfolders. Adopted the CLAUDE_PROJECT_DIR
pattern (sh -c 'exec node "${CLAUDE_PROJECT_DIR:-.}/..."') which
Claude Code sets to the project root.
Also: removed ruflo/claude-flow permissions from _aqePermissions
injected by aqe init — only AQE-specific entries belong in user
settings. Fixed init-wizard-hooks.ts missing union-merge for
permissions (#362 parity).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hook commands generated by `aqe init` embedded the host machine's absolute
path as a fallback, making settings.json non-portable across machines.
Since Claude Code runs hooks with cwd=project root and the helpers already
use __dirname internally, simple relative paths are sufficient.
Also fixes stale test that asserted on old `permissions` key renamed to
`_aqePermissions` in #362.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hook deduplication: add brain-checkpoint.cjs and .claude/helpers/ patterns to
AQE_COMMAND_PATTERNS so mergeHooksSmart() correctly identifies them as AQE-owned
and removes old copies on re-init instead of accumulating duplicates.
Governance time budget: change budgetRemaining.timeMs to measure idle time since
last action instead of total elapsed since first action, and increase default
idleTimeoutMs from 5 to 15 minutes. Prevents false "Budget exhausted: time"
blocks on requirements_validate and coverage_analyze_sublinear.
Closes#344, closes#345
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update ADRs 075-079 with implementation details, revise the
multi-language GOAP implementation plan, add test generators and
parser test fixtures for Go, Rust, Java, C#, Swift, Python.
Include skill validation schema updates and v2→v3 migration skill.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>