Commit Graph

388 Commits

Author SHA1 Message Date
Dragan Spiridonov b4374f220b fix(bridge): preserve domain-specific fan-out per #484, parametrize tests
Rescoped per @Jordi-Izquierdo-DDS's filed issue #484 and his Stage A.1
verified shop patch 050:

- KEEP the domain-specific fan-out events (test-execution.TestRunCompleted,
  coverage-analysis.CoverageGapDetected/CoverageReportCreated,
  test-generation.TestGenerated, code-intelligence.FileChanged) with
  their existing flat basePayload shape. Their handlers were already
  shipped against this shape; changing it would break out-of-tree
  subscribers. Smaller blast radius.
- ONLY change the universal learning.ExperienceCaptured event to use the
  canonical nested { experience: TaskExperience-shaped, reward } shape.

Tests parametrized across multiple non-fan-out domains
(requirements-validation, security-compliance, visual-accessibility) per
Jordi's #484 test improvement suggestion — these exercise the
universal-event path exclusively, which v3.9.28's test-execution-only
test inadvertently masked via the fan-out's side-effect kv write.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:16:00 +00:00
Dragan Spiridonov f7acdd5707 chore(release): bump version to v3.9.29
Hotfix for v3.9.28 — bridge payload shape (#482 round 3)

After v3.9.28 fixed the subscriber-loading order, handlers fired for
every bridge event but immediately short-circuited because
event.payload.experience was undefined. The bridge had been publishing a
flat payload { experienceId, domain, agent, task, ... } that didn't
match handleExperienceCaptured's destructure.

Fix: bridge now publishes the canonical nested
{ experience: TaskExperience-shaped, reward } shape that matches the
existing publisher in src/learning/experience-capture.ts:1043.

Also dropped the domain-specific fan-out events (test-execution.TestRunCompleted,
coverage-analysis.CoverageGapDetected, etc.) — their handlers expect
domain-event-specific fields (runId, passed, failed, gapId, riskScore)
that hooks don't capture, so publishing them with undefined fields
recorded degenerate experiences. Universal learning.ExperienceCaptured
is now the bridge's sole publication.

Integration test now uses requirements-validation domain (per Jordi's
suggestion) so the universal-event path is the sole thing being tested,
not masked by a fan-out side effect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:56:00 +00:00
Dragan Spiridonov 062b413b70 chore(release): bump version to v3.9.28
Hotfix for v3.9.27 — bridge subscriber wiring (#482)

The CapturedExperienceBridge shipped in v3.9.27 published events into a
kernel with no subscribers because lazyLoading: true left domain plugins
un-initialized when the bridge's first drain ran. Cursor advanced past
the rows; events were silently lost.

Fix: kernel.initialize() now eagerly loads all enabled domain plugins
before starting the bridge. CLI commands opt out via the new
enableExperienceBridge: false flag to keep their fast startup. Added
end-to-end integration test (real kernel + real plugin + real drain →
asserts kv_store has learning:experience:* key).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 09:50:54 +00:00
Dragan Spiridonov 4e011a81d0 chore(release): bump version to v3.9.27
- AbortSignal threading bounds ReasoningBank.initialize() (#478)
  prevents leaked init from runaway patterns.rvf writes
- CapturedExperienceBridge wires hook activity to domain plugins (#479)
  via kernel-side drain of captured_experiences
- Removes dead v3-qe-bridge.sh, two stale planning docs, five orphan
  workers in qe-workers.ts (subsumed by LearningConsolidationWorker)

Net: +430 / -2,090 lines

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 09:10:11 +00:00
Dragan Spiridonov bb34aeace4 chore(release): bump version to v3.9.26
Ten learning-pipeline fixes (#453, #454, #455, #456, #460, #461, #462,
#463, #464, #465) plus dup closures (#457-#459). Tightens the #465
sentinel sweep with the same task_json discriminator the LIMIT-1 close
uses, preserving the #451 ownership split (route sentinels owned by
post-route, pre-task sentinels by post-task). Updates the regression
suite to reflect the new sweep behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 14:20:24 +00:00
Dragan Spiridonov b2e6090c6d chore(release): v3.9.25 (#452)
* feat(hooks): post-route Stop hook closes route sentinels 1:1 (#451)

The `route` hook fires on UserPromptSubmit and writes a sentinel row to
routing_outcomes with quality_score=-1, expecting `post-task` to close
it. But `post-task` only fires on PostToolUse ^(Task|Agent)$, which is
rare in direct-work sessions (Bash/Edit/Read without spawning sub-
agents). Sentinels accumulated indefinitely — Jordi reported 123+
unresolved rows per session. Stream D never converged.

Changes:

1. New `aqe hooks post-route` subcommand
   (src/cli/commands/hooks-handlers/routing-hooks.ts)
   Closes the most-recent unresolved route sentinel using a
   `task_json NOT LIKE '%"taskId"%'` discriminator that isolates
   route entries from pre-task entries. Quality formula collapses the
   6-dim outcome formula for unknown duration:
     0.325 + 0.25·success + 0.10·1.0
   = 0.675 (success) / 0.425 (failure)

2. Inverse discriminator on updateRoutingOutcomeQuality
   (src/cli/commands/hooks-handlers/hooks-dream-learning.ts)
   Added `task_json LIKE '%"taskId"%'` to the WHERE clause so
   post-task only ever closes pre-task sentinels. Without this,
   post-task could grab a stale route sentinel by accident and
   miscredit duration to a row that wasn't about a Task() call.
   Symmetric counterpart to the post-route filter.

3. Stop-hook wiring in both init template paths
   (src/init/phases/07-hooks.ts + src/init/init-wizard-hooks.ts)
   Added `npx agentic-qe hooks post-route --success true --json`
   to the Stop block. Timeout 5000ms, continueOnError: true, so a
   failed post-route cannot block session teardown.

4. CLI help text (src/cli/commands/hooks.ts)
   Added example for the new subcommand.

5. Regression test (tests/unit/cli/commands/post-route.test.ts)
   4 tests using in-memory better-sqlite3:
   - Closes most-recent route sentinel; leaves pre-task sentinels
     and resolved rows untouched
   - quality_score = 0.425 when --success false
   - No-op when only pre-task sentinels exist (discriminator works)
   - No-op on second invocation when only one sentinel was outstanding

Bug-introduce verification: stashed routing-hooks.ts, ran new test —
all 4 cases failed (Commander rejects unknown subcommand). Restored
fix, all 4 pass. Test distinguishes pre-fix and post-fix states.

Co-authored-by: Jordi Izquierdo <noreply@github.com>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(release): bump version to v3.9.25

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 15:05:29 +02:00
Dragan Spiridonov ca714ac1a7 chore(release): v3.9.24 (#450)
* fix(hooks): post-task runs Stream B/D/F when --task-id is missing (#449)

The shipped PostToolUse hook command for Task/Agent matchers is
  `npx agentic-qe hooks post-task --task-id "$TOOL_RESULT_agent_id" --success --json`
Claude Code does not populate $TOOL_RESULT_agent_id, so the flag arrives
empty and options.taskId is falsy on every real hook invocation. The
`if (options.taskId)` gate inside post-task then short-circuited the
entire Stream B/D/F learning chain:

- reasoningBank.recordOutcome — never called
- persistTaskOutcome — never called (no captured_experiences,
  experience_applications, qe_trajectories, dream_insights.applied)
- updateRoutingOutcomeQuality — never called (routing_outcomes
  sentinels accumulated unfilled at success=0/quality_score=-1)
- updateHookRouterQValue — never called (rl_q_values stayed empty
  forever)

Same regression was fixed in v3.9.21 (patch 030) and silently came
back in v3.9.23.

Fix:
- Remove the `if (options.taskId)` gate in post-task. Use
  `hook-${Date.now()}` fallback for the patternId / experience id
  when the caller didn't supply one. The bridge lookup in
  persistTaskOutcome keys by `ORDER BY created_at DESC LIMIT 1`
  (not by taskId), so Stream F's Bellman Q-update still finds the
  bridge payload it needs.
- Remove the parallel `&& options.taskId` clause from the pre-task
  routing_outcomes sentinel write at line 195 — same root cause.
- Add `DO NOT REINTRODUCE` comment blocks at both sites pointing
  at #449 and patch 030.

Test: tests/unit/cli/commands/task-hooks-no-taskid.test.ts mocks
hooks-shared and asserts persistTaskOutcome / updateHookRouterQValue
fire when --task-id is absent. Bug-introduce verification:
re-introducing the gate makes the no-taskId test fail with the
expected "called 1 times, but got 0 times".

Co-authored-by: Jordi Izquierdo <noreply@github.com>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(release): bump version to v3.9.24

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 09:54:33 +02:00
Dragan Spiridonov 1967be2928 fix(learning): qe_pattern_usage stays 0 + exclude flaky tests from fast suite
Closes #447. Three-layer fix for the upsert-returns-wrong-UUID bug that
silently broke Stream C of self-learning:

* sqlite-persistence.ts: SELECT actual id after ON CONFLICT(name,
  qe_domain, pattern_type) — the upsert keeps the existing row's UUID
  but we were returning the input one, leaving downstream callers with
  a UUID that didn't exist in qe_patterns.

* rvf-pattern-store.ts: capture the SQLite return value and realign
  pattern.id BEFORE the HNSW ingest so the index keys stay consistent
  with the source-of-truth table.

* qe-hooks.ts QEAgentCompletion: change const → let on
  effectivePatternId, capture storeResult.value.id from the auto-create
  storePattern call, feed it into recordOutcome. Without this, every
  auto-created pattern's outcome silently failed with "Pattern not
  found", which is why qe_pattern_usage stayed at 0 forever.

Also (#448): excluded tests/unit/learning/qe-reasoning-bank.test.ts and
aqe-learning-engine.test.ts from test:unit:fast — both chronically hang
the vitest fork worker on heavy module graph load. Same pattern as
domain-handlers.test.ts already excluded from test:ci. Issue #448 tracks
the root-cause investigation.

Thanks to @Jordi-Izquierdo-DDS for the #447 diagnosis.

Co-Authored-By: Jordi Izquierdo <jordi-izquierdo-dds@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:54:21 +00:00
Dragan Spiridonov 806ade7e25 chore(release): bump version to v3.9.23 (#446)
Fixes routing learning loop — bootstrap patterns now reach HNSW index
(#445). After this release, `patternCount` in routing hook output is
non-zero, existing installs auto-backfill `.agentic-qe/patterns.rvf` from
SQLite on next startup.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:49:17 +02:00
Dragan Spiridonov 2ee349d59c chore(release): bump version to v3.9.22
- package.json + package-lock.json: 3.9.21 → 3.9.22
- .claude-plugin/plugin.json: 3.9.21 → 3.9.22
- .claude/skills/skills-manifest.json: fleetVersion 3.9.21 → 3.9.22
- assets/skills/skills-manifest.json: fleetVersion 3.9.21 → 3.9.22
- CHANGELOG.md: add 3.9.22 entry
- docs/releases/v3.9.22.md: new release notes
- docs/releases/README.md: add 3.9.22 row

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 13:33:55 +00:00
Dragan Spiridonov c09343c92a chore(release): bump version to v3.9.21
Bumps version + fleetVersion across package.json, plugin.json, and the
two skills-manifest.json copies. Adds CHANGELOG entry and release notes.

Includes one fix discovered during the release-prep e2e: stale-lock
recovery in shared-rvf-adapter's openOrCreateRvf ladder. The native
@ruvector/rvf-node binding leaves a `<file>.lock` artifact when a
process exits without calling close() — a behaviour that frequently
happens in CLI flows and that the previous always-create code path
masked. With open-or-create, those stale locks now surfaced as
`LockHeld` errors. The ladder now detects that, removes the stale
lock file, and retries open exactly once. E2E confirms RVF native
recovers cleanly across init → CLI invocation boundaries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 12:55:36 +00:00
Dragan Spiridonov 5d187de2a1 fix(install,rvf,hypergraph): unblock Windows install, fix RVF FsyncFailed, synthesize covers edges
Bundles fixes for issue #439 (Windows install) and Jordi RUFLO patches
P020 (RVF init) + P220 (hypergraph blindness).

Windows install (#439):
- Move hnswlib-node from dependencies to optionalDependencies so
  installs no longer fail on Windows boxes without VS C++ Build Tools;
  HnswAdapter already routes around a missing native binary at runtime.
- Replace HNSWIndex.ts top-level static `import hnswlib from
  'hnswlib-node'` with a lazy require so package load survives the
  optional dep being absent.
- README + preinstall.cjs: document toolchain requirement and disclose
  that the JS fallback degrades to O(N) brute-force when @ruvector/gnn
  is also unavailable (Windows default — no win32 prebuilds ship).
- ADR-090 amendment reconciling the move with ADR-081's optional-dep +
  JS-fallback intent.

RVF init (Jordi P020):
- Root cause: shared-rvf-adapter and pattern-store factory always called
  RvfDatabase.create(), which throws `0x0303 FsyncFailed` when the .rvf
  file already exists from a prior init phase. Reproduced and confirmed
  against both 0.1.7 and 0.1.8 native binaries — not a version
  regression.
- Fix: race-tolerant open-or-create ladder (try open → fall back to
  create → retry open on create-race) with dim() verification after
  open. Mismatched-dim files are closed and the caller degrades rather
  than corrupting silently.

Hypergraph (Jordi P220):
- Drop the original flushEdgesToHypergraph (wrote `call`/`extends`
  edges that no production query reads — devil's-advocate review caught
  it as dead infrastructure).
- Add HypergraphEngine.synthesizeTestCoverage that re-tags test files
  type='test' and writes `covers` edges from each test file to
  functions in the source files it imports. This is the shape
  findUntestedFunctions / findImpactedTests actually filter on.
- E2E verified: untested correctly excludes covered functions;
  impacted-tests returns the right test file.

Verification:
- `npm run build` clean
- 276/276 tests pass across HNSW, RVF, KG, coordinator, hypergraph
  suites (5 new synthesizeTestCoverage tests; replaced 4 obsolete
  flush tests)
- E2E on fresh project: aqe init clean, hooks stats shows
  nativeAvailable: true, code index logs `Test coverage synthesized`,
  hg untested + hg impacted return useful results

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 12:22:58 +00:00
Dragan Spiridonov 3ef5fdbd7c docs(release): add v3.9.20 entry to CHANGELOG and releases index
Caught during pre-PR gap audit: per CLAUDE.md release rule, version
bumps must update every hardcoded reference. Missed CHANGELOG.md and
docs/releases/README.md in the initial bump commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 08:16:53 +00:00
Dragan Spiridonov 1a4a7ff9fb chore(release): bump version to v3.9.20
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 07:47:01 +00:00
Dragan Spiridonov ec451c419f chore(release): bump version to v3.9.19 2026-05-05 16:53:24 +00:00
Dragan Spiridonov 25b6bd732a chore(release): v3.9.18
Bundles 4 MCP bug fixes + new agentic-qe-fleet plugin.

Fixed:
- coverage_analyze_sublinear and other domain MCP tools blocked by governance
  after 1-2 calls (synthetic token-slope estimate replaced with 0; throttle
  decisions are no longer treated as hard blocks)
- test_generate_enhanced framework=jest produced unrunnable tests (now emits
  @jest/globals imports instead of invalid 'jest' package import)
- generated test imports referenced /tmp/aqe-temp-* paths (importPathOverrides
  plumbed through IGenerateTestsRequest end-to-end)
- qe/coverage/gaps error message misled callers about which input failed
  (distinguishes coverageFile-empty vs autodiscovery-miss)

Added:
- test_generate_enhanced schema exposes framework, filePath, coverageGoal,
  aiEnhancement, detectAntiPatterns parameters
- agentic-qe-fleet Claude Code plugin (11 agents, 9 commands, 9 skills)
- scripts/smoke-test-fixes.sh and scripts/plugin-load-test.sh

Verification:
- 1301 MCP unit tests pass (zero regressions)
- 734 targeted unit tests pass across changed code
- aqe init --auto in fresh project succeeds (85 skills, 60 agents)
- End-to-end MCP smoke test passes 5/5
- qe-coverage-specialist agent re-spawn confirms NO_GOVERNANCE_BLOCK
- Plugin structural validation: 14/14 checks pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 14:39:10 +00:00
Dragan Spiridonov 087caf41dd docs(release): add v3.9.17 release notes
Per /release skill §4b — release notes file at docs/releases/v3.9.17.md
plus index row at the top of docs/releases/README.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 06:28:12 +00:00
Dragan Spiridonov baecaf9865 chore(release): bump version to v3.9.16
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 12:20:33 +00:00
Dragan Spiridonov 70e900e0f9 feat(adr-091): promote to Implemented + trust_tier 3
Promotion gate documented in ADR-091 (first green CI run of
test-qe-browser.yml against real Vibium) cleared at commit
fae9fd30 / workflow run 24776640163 on 2026-04-22:

- Unit tests (CommandEvalRunner + primitives): success
- Smoke test (real Vibium + httpbin): success
- aqe eval run against real Vibium: success

Changes:
- .claude/skills/qe-browser/SKILL.md: trust_tier 2 -> 3
- ADR-091 status: In Progress -> Implemented, gate marked cleared
- v3-adrs.md index row: In Progress -> Implemented, counts
  updated 79->80 Implemented, 7->6 In Progress

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 11:54:51 +00:00
Dragan Spiridonov 5f58b279d6 chore(release): bump version to v3.9.15
ADR-091 (qe-browser) promoted to Implemented, trust tier 3:
- new aqe eval run --skill <skill> CLI executes skill eval YAMLs as real CommandRunner evals
- aqe init --auto on Linux ARM64 now prints an exact VIBIUM_BROWSER_PATH hint
- docs/guides/qe-browser-getting-started.md for new users
- .github/workflows/test-qe-browser.yml gates PRs with vitest + smoke + eval jobs
- qe-browser eval YAML reworked to use httpbin.org (no fixture server needed)
- Vibium pin comment corrected: ^26.3.18 is a major-line pin, not major.minor

No breaking changes. CLI surface additions only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 07:17:14 +00:00
Dragan Spiridonov cda9fb3c05 fixup(adr-091): address devil's-advocate review
Single commit covering the 5 concrete findings from the qe-devils-advocate
review. Does not change the underlying CommandEvalRunner design or the 5
primitives — only the claims around them and the fixture-server hack the
yaml had silently inherited.

1. Revert promotion (G4): trust_tier 3 -> 2 in SKILL.md; ADR-091 status
   Implemented -> In Progress (2026-04-21); v3-adrs.md index row updated
   to reflect the same; counts 80->79 Implemented, 6->7 In Progress.
   The promotion gate is now documented on ADR-091: first green CI run
   of test-qe-browser.yml (unit + smoke + eval against real Vibium)
   before trust_tier 3 / Implemented are restored.

2. Fix yaml fixtures (G3): tc006/tc007 were referencing
   http://localhost:8088/qe-browser/SKILL.md.html which required an
   unstarted fixture server, so `aqe eval run --skill qe-browser` would
   have failed on a fresh machine. Rewrote both to use https://httpbin.org/html
   (matching scripts/smoke-test.sh tc006/tc007). Dropped tc009
   (poisoned-page check-injection) from the yaml — it needs the local
   serve-skills.js fixture which is out of scope for CommandEvalRunner.
   Documented as an explicit GAP comment in the yaml, noted that
   check-injection.js's severity path is unit-tested at
   tests/unit/scripts/qe-browser-check-injection.test.ts. yaml test_cases
   now 11 -> 10.

3. Correct pin comment wording (G1): the previous comment claimed
   ^26.3.18 was a "major.minor-line pin" — that's factually wrong under
   npm semver (^26.3.18 accepts 26.99.x). Rewritten to accurately
   describe the intent: major-line pin that blocks 27.0+ while
   allowing auto-uptake of 26.x security patches and additive features,
   with scripts/smoke-test.sh as the belt-and-suspenders API contract
   gate. The spec itself stays ^26.3.18 — the correct choice for an
   end-user tool under semver assumptions.

4. Add eval CI job (G2): third job in test-qe-browser.yml runs
   `aqe eval run --skill qe-browser --model claude-3.5-sonnet` against
   a real Vibium install after `npm run build`. This is the
   end-to-end proof that CommandEvalRunner dispatch works that the
   previous unit tests (all mocked CommandRunner) could not provide.
   Uploads the eval JSON as a CI artifact for post-run inspection.
   actionlint clean.

5. Scrub stray files (G5): git rm the coherence-comparison artifacts
   from docs/reports/ that were swept in by a prior `git add -A`, and
   added a focused pattern to .gitignore (not a blanket docs/reports/
   ignore) so future sessions can't repeat the mistake while intentional
   reports can still be committed.

Tests: 51 relevant tests still pass (3 files: command-eval-runner,
command-eval-runner-qe-browser, browser-engine-installer).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 14:09:37 +00:00
Dragan Spiridonov 23416e1577 feat(adr-091): promote to Implemented — trust_tier 3, platform hint, yaml/smoke unify
Closes GAP-05, GAP-08, and final verification gate.

- Linux ARM64 diagnostic (GAP-05): browser-engine-installer now probes
  os.platform + os.arch on Linux aarch64 and checks a prioritized list
  of system chromium locations (/usr/bin/chromium, chromium-browser,
  google-chrome, google-chrome-stable, /snap/bin/chromium). When a
  browser is found, the install result carries a PlatformHint with an
  exact VIBIUM_BROWSER_PATH export the user can copy. When none exists,
  the hint surfaces the `apt-get install chromium` remediation. Wired
  into phase 09 so it prints after vibium install succeeds. 5 new tests.
- GAP-08: added explicit `vibium --headless viewport 1280 720` setup
  steps to yaml tc006/tc007 so the eval runs are as deterministic in CI
  as smoke-test.sh. Updated smoke-test.sh header to note the yaml is
  the canonical spec and the bash script is its mirror (covers the F1
  vibium-missing contract case the yaml can't express cleanly).
- Trust tier promoted 2 -> 3 now that (a) the eval is runnable via
  CommandEvalRunner, (b) CI runs both unit tests + smoke gate, and
  (c) all 11 dependent browser-using skills either reference qe-browser
  or document their intentional Playwright fallback.
- ADR-091 status: Proposed -> Implemented (2026-04-21).
- v3-adrs.md index reflects 80 Implemented / 6 In Progress / 3 Proposed.

Verification: 643/643 tests pass across tests/unit/validation/,
tests/unit/init/, tests/unit/scripts/qe-browser-*.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:25:26 +00:00
Dragan Spiridonov 4739237cd8 feat(adr-091): migrations, getting-started doc, CI workflow
Closes GAP-03a, GAP-03b, GAP-06, GAP-07, and revises GAP-09.

- Rephrased Playwright references in enterprise-integration-testing and
  pentest-validation to point at qe-browser (batch/assert/check-injection)
  so the AQE fleet's canonical browser runner is the recommended tool.
- accessibility-testing: added qe-browser / a11y-ally as the preferred
  axe-core integration path ahead of the Playwright example; Playwright
  kept as a documented fallback for Firefox/Safari or existing suites.
- GAP-09 revised: visual-testing-advanced and compatibility-testing are
  intentional hybrids, not unfinished migrations. visual-testing-advanced
  already labels its Playwright section "LEGACY: fallback"; compatibility
  -testing notes that Vibium's BiDi backend is Chrome-only at v26.3.x so
  Firefox/Safari coverage still needs Playwright. Both stay as-is.
- Added docs/guides/qe-browser-getting-started.md covering install,
  smoke check, eval run, and the 5 primitives with example CLI calls.
- Added .github/workflows/test-qe-browser.yml gating PRs that touch the
  skill, its installer, or CommandEvalRunner. Job 1 runs the full vitest
  sweep; Job 2 installs a pinned Vibium and runs smoke-test.sh against
  real httpbin fixtures.
- Workflow validated with actionlint 1.7.1 (clean).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:16:44 +00:00
Dragan Spiridonov e7a78910d5 chore(release): bump version to v3.9.14
Security + supply-chain hardening closes five P0 release blockers from
the v3.9.13 QE audit. Shipped tarball drops 52% (19.9 MB → 9.6 MB),
15 critical runtime npm vulnerabilities are eliminated, and a
command-injection path in `aqe learning repair` is closed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 14:14:14 +00:00
Dragan Spiridonov 7a254cbd45 docs(qe): add v3.9.13 follow-up research memos (guidance strategy, agent recount)
Two targeted investigations opened while triaging the v3.9.13 QE audit
priority matrix:

1. @claude-flow/guidance strategy — recommendation: keep + demote to
   optionalDependencies. No newer stable version exists on npm; usage is
   already try/await-import/catch-fallback pattern across 62 refs in 17
   files; the only real concern (protobufjs CWE-94 supply-chain) is
   already neutralised by the v3.9.14 overrides.

2. QE agent count recount — verdict: the "60 specialized QE agents"
   claim is honest, not an overcount. Primary fleet is 53 qe-*.md under
   .claude/agents/v3/ plus 7 TDD/review subagents under
   .claude/agents/v3/subagents/qe-*.md. Both sets mirror into
   assets/agents/v3/ for npm distribution. The earlier honesty-audit
   finding undercounted by 7 because subagents were not enumerated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 12:46:40 +00:00
Dragan Spiridonov 558b1d86c7 docs(qe): add v3.9.13 full-quality audit (12 reports, 11 swarm agents)
QE Queen orchestrated parallel analysis across code complexity, security,
performance, test quality, product/QX, dependency health, API contracts,
DDD architecture, accessibility, brutal honesty, and CI pipelines.

Composite score 7.0/10 (+0.1 vs v3.8.13). First honesty-score reversal in
five cycles (68 → 74). CI fully recovered (+4.5) with test-gated npm
publish. Dual MCP server divergence resolved. Surfaced new release
blockers: 15 critical runtime npm vulns via protobufjs chain and 79%
tarball bloat from stale code-split chunks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:12:33 +00:00
Dragan Spiridonov 4a2d8a66da chore(release): bump version to v3.9.13
Ships ADR-093 Opus 4.7 migration: Sonnet 4.6 becomes the fleet-wide
default, xhigh effort level is on everywhere, Opus 4.7 is the opt-in
escalation target via MultiModelExecutor, and cyber-sensitive agents
stay pinned to Sonnet 4.6 pending Cyber Verification Program approval.

Also fixes two stale integration-test assertions that still expected
the retiring claude-haiku-3-5 ID; both now assert the current
claude-haiku-4-5 per the model registry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:01:37 +00:00
Dragan Spiridonov 864741a757 docs(adr-093): mark Accepted — Phases 1, 2, 4 implemented; Phase 3 not required
Status moves from Proposed to Accepted. Phase 3 thinking-config shim
dropped from scope after codebase sweep confirmed no raw-Messages-API
callers pass {type: enabled, budget_tokens: N}. Remaining work tracked:
Cyber Verification application submission (external) and 30-day
telemetry recalibration (~2026-05-17).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 16:39:21 +00:00
Dragan Spiridonov 7f01310556 fix(adr-093): aqe init + skill evals + settings routing use new models
New user projects created via aqe init will now receive the post-ADR-093
model set (Opus 4.7 / Sonnet 4.6 / Haiku 4.5) instead of retiring IDs.

* src/init/kiro-installer.ts: 4 hardcoded model fallbacks updated.
  claude-sonnet-4 → claude-sonnet-4-6 (default + priority=critical),
  claude-opus-4 → claude-opus-4-7 (opus-detected path),
  claude-haiku-4 → claude-haiku-4-5 (haiku-detected path).
  Affects: runtime agent transformation, default QE agent template
  (writeDefaultQEAgent).
* src/init/init-wizard-steps.ts, src/init/phases/12-verification.ts:
  generated aqe.yaml advisor block comment updated to
  anthropic/claude-opus-4.7 so wizard-produced configs point to the
  right advisor model out of the box.
* .claude/settings.json:188-189: claudeFlow.modelPreferences
  default claude-opus-4-5-20251101 → claude-opus-4-7,
  routing claude-3-5-haiku-20241022 → claude-haiku-4-5-20251001.
* Skill eval YAMLs (both .claude/ and assets/ copies):
  api-testing-patterns, contract-testing, database-testing,
  testability-scoring — models_to_test list updated from
  claude-sonnet-4 / claude-3-haiku to claude-sonnet-4-6 / claude-haiku-4-5.
* Skill eval schemas (3 copies: .claude, assets, docs):
  skill-eval.schema.json enum extended with claude-opus-4-7,
  claude-sonnet-4-6, claude-haiku-4-5 as accepted values. Old
  entries retained for backward compat with existing eval files.
* Sample outputs (3 copies): modelUsed field updated to
  claude-sonnet-4-6.
* a11y-ally SKILL.md code example (both .claude and assets):
  model: 'claude-sonnet-4-20250514' → 'claude-sonnet-4-6' (this was
  caught by Commit 2's sweep; landed here for audit completeness).

Verification:
* 0 tsc errors
* 392/392 init module tests pass
* npm run build: CLI + MCP bundles rebuilt clean

Not re-running aqe init against a real fixture in this commit —
minimal+non-interactive mode doesn't materialize integration files
(kiro/opencode); full wizard-mode verification deferred until after
PR opens and a maintainer runs init smoke.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 13:40:14 +00:00
Dragan Spiridonov b055560e81 feat(adr-093): set Opus 4.7 as default ADR-092 advisor model
Commit 5 of 6 for ADR-093 (Commit 4 skipped — no thinking-config
callers to shim; documented in the implementation plan).

* src/routing/advisor/multi-model-executor.ts: DEFAULT_ADVISOR_MODEL
  upgraded from 'anthropic/claude-opus-4' to 'anthropic/claude-opus-4.7'.
  When TinyDancerRouter sets triggerMultiModel=true (confidence < 0.80,
  or < 0.85 for security tasks), MultiModelExecutor.consult() now
  dispatches to Opus 4.7 by default via HybridRouter.chat() +
  OpenRouter provider.
* tests/routing/advisor/multi-model-executor.test.ts,
  tiny-dancer-router-advisor.test.ts: update expected provider model IDs.

SWE-bench Verified 87.6% (vs 80.8% Opus 4.6), SWE-bench Pro 64.3%
(vs 53.4%), CursorBench 70% (vs 58%). Vendor-independence preserved —
consultations still flow through HybridRouter's 7 providers per
ADR-043.

Verification:
* 0 tsc errors
* 65/65 advisor unit tests pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 12:46:42 +00:00
Dragan Spiridonov 3ee1fbf518 feat(adr-093): add Opus 4.7, Sonnet 4.6, Haiku 4.5 to model registry
Commit 1 of 6 for ADR-093 Opus 4.7 migration. No runtime behavior change.

* src/shared/llm/model-mapping.ts: add MODEL_MAPPINGS entries for
  claude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5 with
  anthropic / openrouter / bedrock IDs.
* src/shared/llm/model-registry.ts:
  - extend ModelCapabilities with optional supportsAdaptiveThinking,
    supportsEffortXHigh, tokenizerVersion fields (non-breaking)
  - add MODEL_REGISTRY entries for 4.7 (1M context, xhigh, opus-4-7
    tokenizer, $5/$25/MTok), 4.6 (standard 200k, legacy tokenizer,
    $3/$15), 4.5 haiku
  - mark claude-sonnet-4 deprecationDate 2026-06-15 (retired
    alongside Sonnet 4 per Anthropic announcement)
  - mark claude-haiku-3-5 deprecationDate 2026-02-19 (already retired)
  - export DEFAULT_SONNET_MODEL = 'claude-sonnet-4-6',
    DEFAULT_OPUS_MODEL = 'claude-opus-4-7',
    DEFAULT_HAIKU_MODEL = 'claude-haiku-4-5',
    RETIRING_MODELS registry with ISO retirement dates
* tests/unit/shared/llm/model-registry.test.ts: 14 new tests covering
  new registry entries, central constants, and deprecation metadata.
  All 154 tests across registry/mapping/cost-tracker pass.
* docs/implementation/adrs/ADR-093-opus-4-7-migration.md: new ADR
  capturing migration decisions (Sonnet 4.6 as Tier 3 default, Opus 4.7
  as escalation target, xhigh fleet-wide, thinking-config shim,
  Cyber Verification for security agents, Routines/Monitor deferred
  to ADR-094).
* docs/implementation/adrs/v3-adrs.md: ADR-093 index row added.
* docs/implementation/plans/ADR-093-IMPLEMENTATION-PLAN.md: 6-commit
  execution plan with per-commit verification + rollback strategy.
* docs/security/cyber-verification-application.md: Cyber Verification
  Program application draft (submitted 2026-04-17).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 12:16:24 +00:00
Dragan Spiridonov a85a987e3c chore(release): bump version to v3.9.12
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:31:13 +00:00
Dragan Spiridonov dca7dc53d0 chore(release): bump version to v3.9.11
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:05:28 +00:00
Dragan Spiridonov 4b1258c5ab docs(release): rewrite v3.9.10 notes with user-facing value descriptions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:51:40 +00:00
Dragan Spiridonov b02ace1c80 chore(release): bump version to v3.9.10
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:40:25 +00:00
Dragan Spiridonov 24e30e0584 feat(advisor): implement ADR-092 provider-agnostic advisor strategy
Multi-model routing layer with circuit breaking, PII redaction, and
domain-specific prompts for the Queen coordinator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:40:20 +00:00
Dragan Spiridonov 9befc9a647 chore(release): bump version to v3.9.9
Ships qe-browser fleet skill (Vibium engine, ADR-091) — a ~10MB Go binary
replacement for 300MB Playwright with typed assertions, batch execution,
visual-diff, prompt-injection scanning, and semantic intents. 11 skills
migrated to the new engine.

Total skills: 84 → 85. Tier 3 verified: 49 → 50. Manifest: 1.3.0 → 1.4.0.
fleetVersion bumped to 3.9.9 in skills-manifest.json.

See CHANGELOG.md and docs/releases/v3.9.9.md for details.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:44:07 +00:00
Dragan Spiridonov 4354be0321 docs(skills): add qe-browser to user-facing docs + bump counts
qe-browser is a new Tier 3 fleet skill (added in commits cd4ea7e4
through 9c52823e on this branch, per ADR-091). This commit propagates
its existence to the user-facing documentation and manifests that
were still carrying pre-qe-browser counts.

Count changes (AQE skills only; platform skills unchanged):

- Total QE skills:       84 → 85
- Tier 3 verified:       48 → 49
- V3 Domain skills:      23 → 24
- README.md headline:    "74 QE Skills" → "75 QE Skills"
- agentic-qe-intro.md:   "74 total" → "75 total", "114 defs" → "115"

Files updated:
- README.md: bumped headline count, Tier 3 count in tier table,
  "View all X skills" summary, and added a new "Browser Automation (1)"
  category row pointing at ADR-091
- docs/agentic-qe-intro.md: bumped "Selected QE skills (74 total)" to 75,
  added "Browser" category row with /qe-browser, bumped tree "114
  skill definitions" to 115
- .claude/skills/README.md + assets mirror: bumped Summary counts,
  V3 Domain Skills heading, and added qe-browser as a full description
  entry in the V3 Domain Skills list with a link to ADR-091
- .claude/skills/skills-manifest.json + mirror: manifest version 1.3.0
  → 1.4.0, totalSkills 48 → 49, totalQESkills 80 → 81, added new
  "browser-automation" category, bumped skillBreakdown counts,
  updated notes to reference ADR-091
- .claude/skills/trust-tier-manifest.json + mirror: summary.tier3
  49 → 50 (this file already counted one more than skills-manifest),
  total 112 → 113, validationStatus.passing 49 → 50, added qe-browser
  entry to skillsByTier.tier3 list with category "browser-automation"

Historical CHANGELOG entries (v3.9.x and earlier) intentionally left
at 84 — they describe past state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:50:22 +00:00
Dragan Spiridonov 9c52823e0e fix(qe-browser): F1 — implement documented vibium-unavailable contract
Phase 5 UAT discovered the helper scripts surfaced missing-vibium as
`actual: "eval error: vibium binary not found..."` inside a `failed`
envelope. The Fallback Policy in SKILL.md said scripts MUST return
status:"skipped" with reason "browser-engine-unavailable" — that
contract was aspirational. F1 makes it real.

Contract changes:
- lib/vibium.js: ENOENT now throws typed VibiumUnavailableError (with
  stable code:"BROWSER_ENGINE_UNAVAILABLE" for cross-module duck typing)
- New helper unavailableEnvelope() returns canonical skipped envelope
  with top-level vibiumUnavailable:true and output.reason field
- New runOrSkip() wraps each helper's main() and converts the typed
  error into the documented envelope on the way out
- New rethrowIfUnavailable() helper used inside per-script catch blocks
  so missing-vibium bubbles past local "convert exception to fail()"
  handlers — assert.runConsoleCheck/runNetworkCheck/runBrowserSideCheck,
  batch's per-step catch, check-injection main, intent-score main,
  visual-diff main all updated
- emit() now returns exit code 2 for status:"skipped" (was 1)
- Exit code contract documented: 0=success, 1=failed, 2=skipped

Downstream skills can now branch on result.vibiumUnavailable === true
or exit code === 2 instead of grepping the actual string for
"vibium binary not found".

Tests: 103 (was 86). New file qe-browser-unavailable-e2e.test.ts spawns
each of the 5 helpers under PATH=/tmp/fake-bin (node only, no vibium)
and asserts exit 2 + skipped envelope shape. vibium-lib test grew from
10 to 22 cases including VibiumUnavailableError, runOrSkip, exit codes.

Smoke test: 10/10 PASS (was 9/9). New tc011 builds a fake bin dir
inside the smoke test work dir and verifies the contract end-to-end
against the actual installed scripts.

SKILL.md updated:
- Output Contract section now documents all 3 statuses with shapes
  and exit codes
- Fallback Policy replaced generic prose with concrete bash + Node
  snippets that branch on the structured field

ADR-091 Phase 6 documents the change and verification.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 08:56:11 +00:00
Dragan Spiridonov e468038c4d docs(adr-091): Phase 5 — user-perspective verification of qe-browser
Ran fresh `aqe init --auto` against an empty test project at
/tmp/qe-browser-uat and exercised every helper script as a real user.
12 checks documented in ADR-091, all passing:

  1. qe-browser skill installed cleanly
  2. navigate + assert end-to-end against httpbin.org
  3. M5 --threshold=0.42 form parsed live (verified non-default value)
  4. M6 batch pre-validation aborts BEFORE side effects
  5. M7 intent-score returns scored candidates from real form
  6. M4+M8 check-injection --exclude-selector strips body (3595→35 chars)
  7. M2 fixture server binds 127.0.0.1 (verified via banner)
  8. M3 path traversal blocked (HTTP 404 on /etc/passwd.html)
  9. Vibium-missing fallback returns clear actionable error
 10. Installed smoke-test.sh: 9/9 PASS from inside test project
 11. Idempotent re-init: Browser engine line still printed
 12. JSON envelope contract validated on every emit

H6 pre-flight short-circuit confirmed in production:
  "Browser engine: vibium 26.3.18 (already installed)"
The "this can take 1-3 minutes" banner is suppressed when vibium is
already on PATH, matching the documented Phase 2 behavior.

New finding logged as F1 (NOT a Phase 4 regression):
  Helper scripts surface missing-vibium as `actual: "eval error: ..."`
  inside a `failed` envelope. The SKILL.md Fallback Policy says
  downstream skills should report status:"skipped" reason:
  "browser-engine-unavailable". A cleaner contract would be a
  top-level vibiumUnavailable:true flag. Not a blocker.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 08:29:22 +00:00
Dragan Spiridonov 3eb9ccc461 fix(qe-browser): Phase 4 — all 9 medium devil's-advocate findings
M1 visual-diff threshold: documented "max difference fraction" convention
matching Playwright maxDiffPixelRatio (was inconsistent in docs/code).

M2 fixture server bind: default to 127.0.0.1 instead of 0.0.0.0;
QE_BROWSER_FIXTURE_HOST=0.0.0.0 opt-in for explicit external access.
Codespaces auto-forwards 0.0.0.0 ports — this was an unintentional open
server every time the eval ran.

M3 path-traversal guard: replaced startsWith() with path.relative() +
'..'/absolute check. The old guard false-passed sibling-prefix dirs
(/foo vs /foo2) and was fragile on Windows mixed separators.

M4 ANSI escape injection: added sanitizeSnippet() that strips C0 controls
(0x00-0x1F except \t\n) and DEL (0x7F) from every check-injection
finding snippet. Prevents `cat findings.json` from triggering terminal
control sequences embedded in malicious page content.

M5 parseArgs --key=value: split on first '=' so --threshold=0.05 works
alongside --threshold 0.05. Only the first '=' is split so URL/base64
values survive intact.

M6 batch.js pre-validation: added validateAllSteps() that walks every
step's required fields BEFORE the first vibium call. Step 17 typo now
aborts before steps 1-16 execute their side effects.

M7 intent-score bare-x regex: anchored \bx\b in close_dialog scorer so
"fix", "exit", "extra", "sixteen" no longer match. Unicode × and ✕
unchanged.

M8 check-injection --exclude-selector: new flag drops subtrees from
the scan. Page text is read from a CLONE of <body> with matching
elements removed — live page unchanged. Lets docs sites scan their
own pages without self-flagging documentation about prompt injection.

M9 09-assets vibium catch: wrapped raw error with actionable recovery
guidance (`npm install -g vibium`, then re-run `aqe init`).

Hidden bug found and fixed during M2/M3 testing: fixtures/serve-skills.js
existed but had never been run because the repo root is ESM and the file
uses CommonJS require(). Added scoped fixtures/package.json with
"type": "commonjs" matching the existing scripts/package.json pattern.

Tests: 86 unit tests across 7 files (was 50). All pass.
Smoke test: 9/9 still passing against real Vibium v26.3.18.
Mirrored .claude/skills/qe-browser → assets/skills/qe-browser.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 08:13:40 +00:00
Dragan Spiridonov 4e52d573f7 fix(qe-browser): Phase 3 — real Vibium smoke test verified 9/9 passing
User pushed back on Phase 3 attempt 1 ("blocked on linux-arm64"). After
re-verifying upstream — Vibium 26.3.18 IS the latest on npm, Chrome for
Testing across Stable/Beta/Dev/Canary still ships only linux64 (x86_64),
mac-arm64, mac-x64, win32, win64 — installed Debian's native ARM64
chromium + chromium-driver via apt and symlinked them into Vibium's
cache. Then ran the smoke test for real and found four real bugs in
the qe-browser helper scripts that would have shipped broken.

Bugs found and fixed:

1. Eval contract was wrong. lib/vibium.js's vibiumEvalStdin sent
   `console.log(...)` expecting Vibium to capture it. Vibium doesn't —
   `eval` returns the LAST EXPRESSION's value as
   `{"ok":true,"result":"<stringified>"}`. Fix: dropped console.log
   wrappers from assert.js/intent-score.js/check-injection.js; added
   unwrapEvalResult() in lib/vibium.js that parses the envelope and
   JSON-decodes the result string back into our object.

2. lib/vibium.js did not inject --headless. Vibium defaults to visible
   browser, which fails in headless containers with "Missing X server
   or $DISPLAY". Fix: lib/vibium.js prepends --headless unless
   QE_BROWSER_HEADED=1 is set in the env.

3. `vibium screenshot -o /abs/path/foo.png` ignores the directory and
   saves to `~/Pictures/Vibium/foo.png`. Verified live. Fix:
   visual-diff.js passes just the basename, reads from Vibium's actual
   output dir, copies to the requested path, unlinks the source.

4. `vibium screenshot --selector` flag does NOT exist in v26.3.x.
   Verified via `vibium screenshot --help`. Fix: visual-diff.js throws
   a clear error with remediation guidance if a caller passes
   --selector. (B3's "fall back to eval-clip" comment is now removed.)

Plus a real environment-flakiness fix: smoke-test.sh sets
`vibium viewport 1280 720` before tc006/tc007 visual-diff captures
because httpbin.org/html renders at non-deterministic dimensions
(765x672 vs 780x654 observed) when no viewport is set, causing
spurious pixel-diff failures.

Verbatim smoke test result on this codespace:

  Smoke testing against vibium v26.3.18
  PASS  tc001 url_contains on httpbin form
  PASS  tc002 selector_visible h1 on httpbin /html
  PASS  tc003 failing assertion exits 1
  PASS  tc004 batch 3-step happy path
  PASS  tc005 batch stops on first failure
  PASS  tc006 visual-diff baseline created
  PASS  tc007 visual-diff second run matches
  PASS  tc008 check-injection clean page
  PASS  tc010 intent-score submit_form on httpbin form
  PASS: 9  FAIL: 0  SKIPPED: 0

Unit tests still pass: 50/50 (one test had to be updated — it asserted
`buildScript` includes 'console.log', which is now correctly NOT in the
script after the eval-contract fix).

Phase 3 verification COMPLETE per ADR-091. The qe-browser helpers work
end-to-end against real Vibium + real Chromium + pinned httpbin.org
fixtures. The Linux ARM64 chromium-symlink workaround is documented in
ADR-091; user-facing docs in references/migration-from-playwright.md
still need updating (marked as Phase 4 follow-up).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 07:24:40 +00:00
Dragan Spiridonov 07f20e13cf docs(adr-091): Phase 3 attempt 1 — blocked on Linux ARM64 chromedriver
Ran the smoke test in this codespace (linux-arm64). Vibium installed
cleanly (v26.3.18) and the H1 detectVibium fix verified against real
binary output. tc003 and tc005 passed (failure-path tests that don't
need a browser). The other 7 tests failed because Google does not
publish chrome-for-testing for linux-arm64; Vibium downloaded the
linux64 (x86_64) variant which dies under Rosetta with an elf-loader
error.

Workarounds attempted and rejected:
  - apt install chromium → native ARM64 binary works but Vibium
    hardcodes its own cached chromedriver, no --browser-path flag
  - searched the binary for VIBIUM_CHROME_PATH / --browser-path /
    BROWSER env var support → none in v26.3.18
  - System chromium responds at /json/version with CDP, not BiDi;
    would need a BiDi-speaking chromedriver to use --connect

Conclusion: Phase 3 verification cannot complete on linux-arm64. This
is a Vibium upstream platform gap, NOT a qe-browser bug. The qe-browser
script-level integration with the real vibium binary IS partially
verified by the 2 passing tests.

Added "Vibium does not support Linux ARM64 today" to the Negative
Consequences section. PR reopen still gated on running smoke-test.sh
on linux-x64 or mac-arm64.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:09:28 +00:00
Dragan Spiridonov 72e6e2403b fix(qe-browser): Phase 1 blockers from devil's-advocate review + ADR-091
Three correctness blockers identified by qe-devils-advocate review of the
initial qe-browser implementation (PR #420, closed without merge):

B1: intent-score.js String.replace special-char corruption
  - SCORER_JS.replace('__SCOPE__', JSON.stringify(scope)) interpreted $&,
    $`, $', $1-$9 in the replacement string. Scopes like
    div[data-x="$amount"] silently corrupted the generated script.
  - Fix: split('__TOKEN__').join(value) for literal substitution.
  - Tests: 4 new regression tests covering $&, $', $1, intent placeholder.

B2: assert.js fail-OPEN on console/network telemetry errors
  - runConsoleCheck/runNetworkCheck used to return ok:true when
    `vibium console --json` failed for any reason. no_console_errors
    silently reported pass when telemetry was unavailable.
  - Fix: new unavailable() sentinel returns ok:false + unavailable:true.
    runCheck surfaces it via a new `unavailable` field. Summary
    distinguishes "assertion failed" from "telemetry unavailable".
  - Bonus (H5): expected-field uses ?? not || so element_count {count: 0}
    reports `expected: 0` instead of `null`.
  - Tests: 2 new regression tests on the sentinel + element_count zero.

B3: visual-diff.js dead fallback comment
  - Source comment promised "fall back to eval-clip if not present" but
    no fallback existed. Direct violation of feedback_no_unverified_failure_modes.
  - Fix: comment removed; specific error handler added for unsupported
    --selector flag with clear remediation message. No fake fallback —
    silently substituting full-page would produce wrong baselines.

Plus: ADR-091 documents the Vibium-as-engine decision with full
rejected-alternatives section (dev-browser, gsd-browser, Playwright MCP,
status quo, build-from-scratch), four implementation phases, and a risks
table tracking the 11 devil's-advocate findings with status. Phase 3
(real Vibium install + smoke test) is explicitly gating PR reopen.

Verification:
  - 420/420 tests pass (387 init + 33 qe-browser, 6 new regression tests)
  - npm run build: clean
  - eslint on touched files: clean
  - All 6 helper scripts pass node --check

Branch is intentionally not pushed and PR is intentionally not reopened
until Phase 2 (H1, H2, H4, H6, H7, H8) and Phase 3 (real Vibium smoke
test) are complete.

Refs: docs/implementation/adrs/ADR-091-qe-browser-skill-vibium-engine.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 18:36:20 +00:00
Dragan Spiridonov d2977a57a9 docs(release): embed verification matrix in v3.9.8 release notes
First live execution of the #409 tooling. Generated from npm-publish.yml
run 24132328008 via ./scripts/embed-verification-matrix.sh — all 4
release-gate corpus fixtures passed all 22 assertions in 6m 20s.

Refs: #409, v3.9.8

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 11:29:19 +00:00
Dragan Spiridonov 9f5d967aed chore(release): bump version to v3.9.8
Release-process maturity release. No source code changes since v3.9.7
— every commit lands in CI infrastructure, fixtures, scripts, or docs.
The published package is functionally identical to v3.9.7 except for
a refreshed lockfile carrying two transitive security patches.

Closes 4 of the 5 #401 follow-up issues:
- #408 PR template CI enforcement (#416)
- #409 VERIFICATION.md + matrix embed (#417)
- #410 Weekly chaos workflow (#417)
- #411 Mirror init-corpus tarballs to GitHub Releases (#415)

Plus #414 (dependabot transitive bumps: hono 4.12.9→4.12.12,
@hono/node-server 1.19.11→1.19.13).

The remaining #401 follow-up is #407 (worker_threads phase 06
isolation), which stays deferred per its own definition — none of
its 4 trigger conditions have fired.

Verification (per docs/policies/release-verification.md):
- npm run build — clean (CLI + MCP bundles report v3.9.8)
- npm run typecheck — clean (zero errors)
- 711/711 unit tests pass on the critical CLI subset + the load-
  bearing phase 06 watchdog test
- 15/15 performance gates pass
- Clean-room install: npm pack -> fresh project -> npm install ->
  aqe --version returns 3.9.8 with exit 0
- aqe init --auto --json in fresh project: zero step errors, 84
  skills installed, 60 agents installed, MCP configured, CLAUDE.md
  generated, workers started

Full test:ci suite intentionally not run locally per CLAUDE.md
("DO NOT run local tests in Codespace if they OOM — CI tests in
the workflow are sufficient"). The release-gate corpus + post-
publish canary will exercise the full surface in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:31:15 +00:00
Dragan Spiridonov 4f340bc183 feat(verification): chaos workflow + VERIFICATION.md + matrix embed (#409, #410)
Closes the two remaining init-corpus follow-ups from #401 in one PR:
makes the verification layer visible to humans (#409) and adds
adversarial-rare coverage to complement the everyday-real release
gate (#410).

# #410 — Chaos workflow

Weekly cron-driven workflow that runs aqe init against 6 pathological
project shapes the everyday-real corpus deliberately doesn't cover.
Per-shape assertion is "exit anything except 124" — the watchdog is
the load-bearing thing under test, not init's ability to make sense
of garbage input. Fail-loudly in the Actions tab; no auto-issue
creation, matching the #411 mirror-test pattern.

Six shapes: utf16le-bom, mixed-line-endings, symlink-loop,
binary-as-text, minified-bundle, control-chars. Generated at runtime
into a tmpdir by tests/fixtures/init-chaos/generate.sh — synthetic
generation is appropriate here per the chaos README's "Why synthetic
generation here" section: chaos tests need controlled adversarial
inputs that don't exist in any real public repo.

Verified locally: ran the generator + ran aqe init against all 6
shapes. All 6 pass with rc=0 against the current build, proving the
generator produces valid shapes and the existing watchdog handles
them today. The workflow exists to catch the day a future change
breaks one of these paths.

# #409 — VERIFICATION.md + matrix embed

New docs/VERIFICATION.md is the maintainer-facing entry point: gate
architecture diagram, how to interpret a failed gate, how to add a
new fixture (links to corpus README), how to embed the verification
matrix into a release notes file.

scripts/embed-verification-matrix.sh downloads the init-corpus-logs
artifact from a given workflow run, parses summary.txt, and emits a
markdown matrix. Status-only (option C from the proposal) — Time and
KG-entries columns are tracked as future work because the gate's
current summary.txt doesn't carry that data and extending it would
touch load-bearing infrastructure that's out of scope.

docs/policies/release-verification.md is fully rewritten around the
post-#401 reality: the manual aqe init checklist that pre-dated the
corpus is removed (the gate now does what it tried to do, with
22 assertions per fixture × 4 fixtures × the load-bearing doubleInit
flag). The Version Update Policy + Workflow sections are preserved
intact — they cover the one class of pre-release error the gate
cannot catch.

CONTRIBUTING.md links to the new VERIFICATION.md from the
Documentation section.

# Housekeeping

Removes 3 stale rows from tests/fixtures/init-corpus/README.md's
deferred-items table: #408 (already merged), #409 and #410 (this
PR). Only #407 remains — its 4 trigger conditions still haven't
fired, so it stays deferred per its own definition.

# Verification of this PR (per #401 rules)

- actionlint passed on .github/workflows/init-chaos.yml (#408 lesson:
  js-yaml is not enough for workflow files)
- bash -n on both new shell scripts
- generator ran cleanly and produced all 6 shapes with the expected
  byte content (verified BOM, line endings, symlink targets, PNG
  signature, single-line bundle size, embedded NULs)
- embed script ran against synthetic summary files (PASS-only and
  mixed PASS/FAIL) — both render correctly
- live smoke test: ran aqe init against all 6 chaos shapes locally
  using the globally-installed aqe binary, all 6 exited rc=0 within
  the watchdog budget
- every link in docs/VERIFICATION.md and docs/policies/release-
  verification.md verified to point at a file that exists

Closes #409
Closes #410

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 09:52:29 +00:00
Dragan Spiridonov 65b2599390 chore(release): bump version to v3.9.7
Release notes + CHANGELOG + fleetVersion bump for v3.9.7. See
docs/releases/v3.9.7.md for the user-facing summary.

Highlights:
  - Release-gate corpus with 4 pinned real public repo fixtures
    (mitt, p-queue, RuView with sha256-pinned regression marker,
    agentic-qe self-dogfood) running `aqe init --auto` end-to-end
    before every publish
  - `aqe init --json` with stable schemaVersion 1 contract and
    stricter exit codes
  - Phase 06 no longer hides non-critical failures behind
    result.success:true (the v3.9.3 failure shape is now structurally
    impossible to ship silently)
  - Post-publish canary re-runs the corpus against the freshly
    published package via real npm CDN edge
  - Watchdog effectiveness unit test covering async-stall branches
  - AQE_SKIP_CODE_INDEX promoted to permanent supported flag

Verification:
  - npm run build — clean
  - npm run typecheck — clean
  - tests/unit/init/ + tests/unit/cli/ — 1084/1084 pass
  - Full corpus gate against /tmp/agentic-qe-3.9.7.tgz — 4/4 pass
    with 22 assertions each
  - Isolated install probe (npm install + aqe --version) — OK
  - aqe security --sast on all touched files — 0 findings

Refs: #401, #412

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:28:54 +00:00
Dragan Spiridonov 77d3f09159 chore(release): bump version to v3.9.6
Headline change: native HNSW search actually works again. The previous
NativeHnswBackend wrapped @ruvector/router 0.1.28's VectorDb, which a
fresh investigation found to have four serious bugs:

  1. HNSW search returned essentially random results — recall@10 ≈ 0%
     on the project's FNV fixture and 10% on textbook unit-Gaussian
     random vectors. The graph walk could not find self-vectors when
     querying with a stored vector.
  2. The VectorDb constructor unconditionally wrote a vectors.db redb
     file to the user's project root, polluting CWD with multi-MB
     files outside .agentic-qe/, in a non-SQLite format that no AQE
     migration or backup tooling knew about.
  3. Process-wide singleton lock — only ONE VectorDb instance could
     exist per process. Subsequent constructors threw "Database error:
     Database already open. Cannot acquire lock."
  4. NAPI dispose did not synchronously release the redb lock — root
     cause of v3.9.5's futex deadlock.

NativeHnswBackend was rewritten to wrap hnswlib-node@^3.0.0 (the
canonical Yury Malkov C++ Hnswlib reference implementation, used by
Pinecone, Weaviate, Qdrant, LangChain, ChromaDB). All four bugs are
gone in one swap. Empirical verification: 100% recall@10 vs the old
10%, faster inserts, multiple instances coexist, no CWD pollution.

useNativeHNSW default is flipped back from false to true (reverting
the v3.9.5 hotfix). Users with large codebases get sublinear HNSW
search by default again.

aqe init now warns when it detects a stale `vectors.db` from the
previous version and suggests `rm vectors.db`. It does NOT auto-delete
(per the data protection rules).

No new dependency was added — hnswlib-node was already in package.json.

Bumps fleetVersion in skills-manifest.json from 3.9.2 (stale) to
3.9.6 to match.

Adds release notes at docs/releases/v3.9.6.md and updates the
release index.

Closes #399. Closes #396 (test-suite cleanup carried over from the
closed PR #403, also in this release).

See ADR-090 for the full decision record and CHANGELOG.md for the
user-facing summary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:13:42 +00:00
Dragan Spiridonov 3e6bd4a6b4 docs(adr): ADR-090 hnswlib-node migration with empirical verification (#399)
Documents the four @ruvector/router 0.1.28 bugs found during the
issue #399 investigation, the empirical verification numbers
showing hnswlib-node fixes all four, the rejected alternatives
(wait for upstream, tune efSearch, brute-force, hybrid threshold),
and the user migration guide for stale vectors.db files.

Includes a comparison table:
  - Recall@10 (1k vectors, default params): 10% → 100%
  - Self-vector found in top-10: NO → YES
  - Auto-creates files in CWD: YES → NO
  - Multiple instances per process: NO → YES
  - Dispose releases resources: NO → YES (immediate JS-side null)
  - Native filter functions: NO → YES
  - Runtime efSearch tuning: NO → YES
  - Resize past initial capacity: NO → YES
  - Insert latency (1k × 384 dim): ~430ms → ~324ms

Cross-references the diagnostic scripts in `scripts/diagnose-issue-399*.mjs`
that reproduce each bug and verify hnswlib-node's correctness on
the same fixtures.

CHANGELOG.md gets a new [Unreleased] section describing the migration,
the removed CWD pollution, and the added test infrastructure. The
release manager will rename [Unreleased] to the next version at
release time.

Refs #399.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:23:23 +00:00