The two "no provider available" tests save and clear provider keys to be
hermetic, but the list went stale when ADR-123 (v3.12.2) added the cognitum and
claude-code providers. Any developer with COGNITUM_API_KEY exported got a
HybridRouter where the test expected undefined — failing locally while passing
in CI, where none of these are set.
Adds COGNITUM_API_KEY, CLAUDE_API_KEY, and ANTHROPIC_AUTH_TOKEN to both
clear-lists. Verified: 17/17 pass with COGNITUM_API_KEY still exported.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
An export killed mid-write (hook timeout, session teardown, SIGKILL) left a
store created but never completed. It could neither be opened (0x0106
ManifestNotFound) nor created over (0x0303 FsyncFailed, path exists), so the
RVF backend stayed silently disabled for the life of the project.
Export is now atomic: build at `<path>.tmp.<pid>`, close, then rename over the
final path. An interrupted export leaves the previous good store untouched.
Stale tmps are swept, skipping any whose owning pid is still alive.
Recovery is wired into all three open paths (dual-writer/brain.rvf, shared
adapter/patterns.rvf, pattern-store ladder): when open AND create both fail the
file is provably unusable, so it is quarantined aside — not deleted — and the
derived cache is rebuilt.
Recovery is deliberately NOT keyed on the signature reported in the issue.
Measured against @ruvector/rvf-node 0.1.8: `FLVR` is the lock record's own
magic (the store's is `SFVR`), so a 104-byte FLVR lock is an ordinary stale
lock, not leaked store bytes; and a valid empty store is exactly 162 bytes,
the size reported as "truncated". Keying on either would quarantine healthy
stores out from under live processes. The lock record does carry its owner's
pid (u32 LE at offset 4), which now guards recovery and also fixes a
pre-existing hazard: stale-lock cleanup previously unlinked locks
unconditionally, breaking live peers.
Also converts three require() calls of source modules to static imports. They
resolve in the esbuild bundle but throw under the test runner, so tests were
silently exercising a different code path than production.
Tests: real SIGKILL mid-export reproduction (previously truncated the store to
162 bytes + stale lock, matching the report), fault-injected export failure,
and recovery through each open path. All fail without the fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The flywheel signed evolve receipts with a self-generated key, so its lineage
could not be attributed to the platform identity that qe-harness evidence bundles
chain to. This wires the bridge:
- platform-signer.ts: platformSigner() derives the deterministic Ed25519 seed from
QE_WITNESS_SIGNING_KEY (JSON {publicKey,privateKey}, the Secret Manager shape
qe-harness Stage-B reads) and hands it to createSigner — reproducing the exact
platform keypair. Graceful: null when the env is absent/malformed (keeps the
self-generated-key behaviour). Env-reading stays out of the receipt.ts core.
- receipt.ts keyIdOf now trims the PEM, matching the platform witness fingerprint
scheme (sha256(pem.trim()) truncated to 16 hex — qe-harness witness.ts /
meta-llm qe-witness.ts). So a platform-signed receipt's keyId equals the
allowlist fingerprint.
Verified against the REAL QE_WITNESS_SIGNING_KEY (no key material logged): the
derived signer's keyId == f1ac28607da49ec1, it is in the real
QE_WITNESS_PUBLIC_KEYS_JSON allowlist, and a signed receipt verifies (tamper
rejected). Tests: +5; existing flywheel suite (34) green; tsc clean.
Refs cognitum-one/qe-harness#7.
Co-Authored-By: Ruflo & AQE
Closes the structural gap from issue #557: AQE could only bill the paid
Anthropic API even for Pro/Max subscribers, and its budget caps were never
enforced.
- claude-code provider: run QE via `claude -p` on the user's subscription;
child env strips API-billing keys so it can't revert to API billing
- Enforced cross-process spend caps (--max-budget-usd / AQE_MAX_BUDGET_USD),
persisted to memory.db (llm_spend); enforced on the ProviderManager AND
HybridRouter paths; over-budget aborts with COST_LIMIT_EXCEEDED
- cognitum provider: OpenAI/Anthropic-compatible gateway with per-request
cost receipts, embeddings, and a server-side hard cap
- Billing-mode taxonomy + startup notice + `aqe health` LLM Billing section
- config-store: honor explicit `enabled: false` over env key presence;
AQE_LLM_PROVIDER selector
- Fix: `aqe eval run` no longer scores fabricated mock responses — real
provider by default, hard-error when none configured, `--mock` opt-in
- Consensus verification path prints a billing warning (deferred full port)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two flaky tests depended on shared/real SQLite state, causing failures only
in the full parallel suite run:
- metrics-tracker.test.ts opened the REAL project .agentic-qe/memory.db via
createLearningMetricsTracker(process.cwd()). A live-DB read threw "database
is locked" under the bind-mounted/parallel runner (and risked corrupting the
project's learning data). Now uses an isolated temp projectRoot with an
empty-but-valid memory.db, exercising the real getDashboardData* code paths
(the tracker probes sqlite_master, so an empty DB returns zeroed metrics).
Adds an explicit "Database not found" test against a missing temp DB.
- sona-persistence.test.ts used a fixed /tmp path, so persisted kv_store state
(the request counter) leaked between tests and flaked the "starts at 0"
assertion. Each test now gets a unique mkdtemp dir, cleaned up in afterEach.
Full unit suite: 17639 passed, 0 failed (previously 5 failed / 2 files).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Non-destructive `aqe init` for `.claude/settings.json`: merge instead of
overwrite, preserve user-owned config (custom statusLine, explicit
includeCoAuthoredBy, AQE_* env overrides, other tools' hooks such as ruflo /
Claude Flow), deep-merge v3 sections, and back up the pristine original before
writing (mirroring CLAUDE.md.backup).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up to 961f3feb. The structural rewrite removed the regex sink (the 9
incomplete-hostname-regexp alerts cleared) but introduced one new alert:
`allowed.replace('*', MARKER)` replaces only the FIRST '*' (CodeQL
js/incomplete-sanitization, "Incomplete string escaping or encoding",
routes.ts:709).
Use the global form `allowed.replace(/\*/g, MARKER)` so every '*' is substituted.
A multi-wildcard pattern is still rejected safely: its suffix then contains the
placeholder label, which no real host can end with. Adds a regression test for a
multi-star pattern.
All 10 validateRedirectUri cases pass; tsc 0 errors; build clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up to 2d63c88c. Bounding the wildcard to `[^./]+` fixed the open-redirect
bypass, but CodeQL's js/incomplete-hostname-regexp still flagged every hostname
allow-list literal that flows into `new RegExp` (it does not model the custom
escaping), so the alert count grew to 9 as the new regression tests added more
`*.example.com` literals.
Remove the RegExp sink entirely: validateRedirectUri now compares parsed URL
components. For a wildcard entry, only the single leftmost subdomain label may be
wildcarded — it must be a non-empty, dot-free label — and protocol/port must match
with an exact-or-prefix path match. This is strictly more secure (a host can never
be spoofed via extra dots or path segments) and eliminates the CodeQL finding at
its root (no URL string is ever compiled into a regex).
All 9 validateRedirectUri cases pass unchanged (6 original + 3 bypass regressions);
tsc 0 errors; build clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
validateRedirectUri expanded an allow-list wildcard with `.replace(/\*/g, '.*')`,
so `https://*.example.com/cb` compiled to `^https://.*\.example\.com/cb$`. Because
`.*` also matches `.` and `/`, an attacker-controlled host could satisfy the
pattern by carrying the allowed suffix in the URL PATH — e.g.
`https://evil.com/x.example.com/cb` validated as allowed → open redirect. This is
the CodeQL js/incomplete-hostname-regexp finding (6 alerts, #214–219) surfaced by
the new a2a auth route tests.
Fix: expand the wildcard to `[^./]+` so it binds to a single subdomain label and
cannot span dots or slashes. Exact, same-origin, path-prefix, and single-label
wildcard matches are preserved; only the previously-exploitable path-injection
spoof and multi-level-wildcard span are now rejected (standard wildcard-cert
semantics). Adds regression tests for the path-injection, multi-label, and
embedded-slash bypasses.
Scope: grepped all `.replace(/\*/g, '.*')` sites — the others are glob→regex
matchers for memory keys / event names / worker patterns (not hostname
validation) where `.*` is intended; only the auth redirect validator is affected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes and supersedes the 2026-07-09 directional DoE (which was 25/27 cells, had
no F-test, and — the reproducibility gap found this session — never persisted its raw
data). Re-run full under the CRIT-2 design (N=5 stochastic replicates of fixed item
A1-inRange, real within-cell error term), qwen local $0 + anthropic/claude-haiku-4.5
+ anthropic/claude-opus-4.8 via OpenRouter. $1.538 total, well under the $11 budget.
Results (real main-effects ANOVA, 135 observations, first real data the aggregator
has ever consumed — previously stub-only):
- scaffold: none 1.000 >> plan-and-solve 0.311 >> reflexion 0.067
F(2,108)=218.9, p=1.0e-38, 71.9% of variance — DOMINANT and strongly NEGATIVE.
Both scaffolds DROP. retort's "more harness lowers reliability", now overwhelming.
- model: qwen3-coder:30b 0.644 > haiku-4.5 0.400 > opus-4.8 0.333
F(2,108)=25.1, p=1.1e-9 — local qwen best & free; opus 5x+ cost = negative value.
(Complete 27/27 reverses the prior unequal-n haiku>opus>qwen ordering, significantly.)
- retrieval: off 0.480 > on 0.433 F(1,108)=1.5, p=0.22 NOT significant, slightly
negative — the ADR-118 flywheel feature-on-trial formally fails as `beads`.
EXPLAINED by the 2026-07-10 coupling finding: A1-inRange is a no-headroom item
the models know cold, so a retrieved exemplar has nothing to add.
- prompt: TDD 0.533 > ATDD 0.467 > neutral 0.378 F(2,108)=5.7, p=4.5e-3.
Changes:
- scripts/doe-run.ts: cloud path rewired from raw Anthropic fetch to OpenRouter
(vendor/model ids, opus-4.8 not opus-4-7, exact per-call cost from usage.cost).
- docs/implementation/doe-run-2026-07-10.jsonl: raw per-cell data persisted IN-REPO
(fixes the gap that lost the 2026-07-09 run's data).
- DOE-HARNESS-SCREEN-DESIGN.md §Results (DEFINITIVE) + ADR-122 status/history updated;
prior directional run retained, marked SUPERSEDED.
Verified: tsc 0 errors; $0 --stub and --smoke pipelines green before the metered run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Runs the CRIT-1 coupling experiment live on qwen3-coder:30b (Ollama, $0) and
characterizes EXACTLY when the ADR-118 flywheel's retrieval helps generated tests.
Result (N=5/condition, mutation-oracle graded, end-to-end "runs∧kills" response):
- POSITIVE CONTROL (POS-reserved — an arbitrary system-specific rule the model
cannot know a priori, a proxy for project-specific corpus knowledge):
NONE 0.00 / IRRELEVANT 0.00 / RELEVANT 1.00 → gain +1.00 COUPLING VALIDATED.
Without the exemplar qwen can't even write a passing test; with it, a perfect one.
- TEXTBOOK (B4-isLeapYear — the century/400 rule):
NONE 1.00 / RELEVANT 1.00 → NO HEADROOM (the model knows the trap cold).
Conclusion: the coupling mechanism is REAL (the harness demonstrably detects it, so
its nulls are live measurements) but HEADROOM-GATED — retrieval improves tests iff
the corpus supplies knowledge the base model lacks. Generic QE edge cases are
already known to code models (30b AND 7b), which is WHY the ADR-122 DoE rated
retrieval `beads`. This explains the prior honest nulls rather than contradicting them.
Getting here required fixing three measure-the-measurement traps that had produced a
FALSE "no coupling" verdict on the first run:
- baseline floored by 500-token truncation (→ 1400) and empty-input over-reach;
- spec leaked the trap (anchor inputUnderTest spells out the edge) → no headroom →
switched to UNDER-SPECIFIED specs graded against the frozen trap-encoding reference;
- metric conditioned on baseline, hiding retrieval's strongest effect (rescuing a
test that otherwise can't be written) → switched to end-to-end usable-quality.
Also:
- OpenRouter wired as the cloud path (vendor/model ids; anthropic/claude-haiku-4.5
et al. confirmed reachable), replacing the rate-limited Anthropic-direct fetch.
- coupled-anchor.test.ts: adds an honest AQE_LIVE_COUPLING-gated end-to-end test that
fails loudly (never fabricates a pass) rather than asserting the mechanism the
scripted unit test only assumes.
- ADR-118 status → "INFRASTRUCTURE WITH A CHARACTERIZED SIGNAL": the flywheel's
retrieval-tuning pays off iff qe_patterns holds knowledge the base model lacks.
Verified: tsc 0 errors; coupled-anchor 1 passed + 1 skipped.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Addresses the CRITICAL/HIGH/MED findings from the brutal-honesty review of the
learning-integrity cluster. The theme: the machinery was real but several claims
outran the evidence. This makes the claims honest and the evidence falsifiable.
CRIT-1 / HIGH-3 (flywheel gated vapor / toy anchor can't move):
- verification/anchors/qe-anchor-v2.json — 5 oracle-verified DISCRIMINATING items
(13 mutants), each with a trap edge a happy-path test misses, so the anchor CAN
actually move. v1's items were too easy to discriminate a retrieval effect.
- scripts/coupling-experiment.ts — falsifiable NONE/IRRELEVANT/RELEVANT controlled
test (N reps, temp>0, $0 mutation-oracle grading). Live run remains blocked on
model availability; the harness refuses to fabricate a verdict.
CRIT-2 (DoE "stats" were a range proxy):
- scripts/doe-run.ts — N real replicates of a FIXED item at temp=0.6 (was 5
different items x1 at temp=0), per-replicate seed, plus a deterministic $0 --stub.
- scripts/doe-aggregate.mjs — real main-effects factorial ANOVA: within-cell error
term, F-test via dependency-free regularized incomplete beta; beads verdict now
gates on p<0.05, not an eyeballed mean delta.
- tests/unit/scripts/doe-aggregate.test.ts — F-CDF + incomplete-beta vs closed
forms/R, planted-effect recovery (p<0.001), null factor (p>0.5), unbalanced cells.
HIGH-4 / MED-6 (over-claimed gate guarantees):
- ADR-120 gains a "Threat model and limits (honest)" section: gateReExecutes
catches a lying log, not a buggy gate (same-process seal+rule).
- ADR-118 status reframed to "infrastructure awaiting a validated signal."
- tests/unit/validation/rule-consistency.test.ts — property test scoping what the
gate actually guarantees (determinism, stable fingerprints, flipped-verdict).
- DOE-HARNESS-SCREEN-DESIGN.md — unequal-n note.
HIGH-5 / MED-7 (self-fulfilling test / brittle scripts):
- tests/unit/learning/mmr-scaling.test.ts — FALSIFIABLE regression for the real
O(n^4) scoreHeldOut hang the MMR_POOL_SIZE cap fixed (96s->420ms at n=300).
- coupled-anchor.test.ts de-faked: relabeled as a MECHANISM/wiring test, documents
that the scripted generator hardcodes the outcome and the real model was an
honest null — no longer readable as evidence that coupling helps.
- tests/unit/validation/sealed-hash-roundtrip.test.ts — regression for the
canonicalJson undefined-key seal bug.
Verification: tsc 0 errors; 33/33 new remediation tests + 290/290 full
validation+flywheel cluster green. No live model run (Ollama offline + Anthropic
account at usage limit) — coupling live-validation surfaced as the one honest
open item, not faked.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The ruflo daemon's audit worker (now disabled) dumped 9 inconsistently-named
LLM-generated SECURITY_AUDIT_*.json / security-audit-*.json reports to the repo
root — headline "hardcoded secrets" was a false positive (public SauceLabs demo
creds), the rest unverified/inconsistent LLM noise. Ignore the pattern so future
stray reports don't clutter git status. Also ignore the option-C WAL-monitor
local artifacts (.agentic-qe/wal-monitor.*, *.moncopy-*).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The reflexion critique-and-revise step sometimes emits an opening ```javascript
fence with no closing ```; the old match-a-closed-block regex then left the fence
line in the generated test → a syntax error → false baseline failure. Strip fence
lines directly so unclosed fences no longer inflate cell failures. Verified
2026-07-09: does not change the ADR-122 scaffold verdict (reflexion's hit is a
genuine over-iteration effect), only removes cross-cell noise.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adopts the receipt-gated self-improvement discipline from the 2026-07 cross-repo
analysis of ruflo (flywheel), MetaHarness (gateReExecutes), and retort (two-gate
spec conformance + DoE). All DI'd and unit-tested (178 tests); run end-to-end on
real qe_patterns; every limitation honestly scoped.
- ADR-117 frozen oracle anchor: hash-pinned, constant-denominator eval set that
no promotion may regress; loader throws on drift (verification/anchors/qe-anchor-v1.json).
- ADR-118 receipt-gated QE-policy flywheel: generational loop over qe_patterns,
conjunctive frozen accept(), Ed25519-signed receipts + compounding lineage,
durable persistence (flywheel_receipts), corpus + semantic-retriever coupling.
- ADR-119 two-gate quality verdicts: mechanical gate + frontier judge, three-valued
(pass/fail/inconclusive) with preflight; new `aqe quality-gate` CLI + `qe/quality/gate` MCP tool.
- ADR-120 gateReExecutes: re-execute a versioned frozen rule on sealed inputs;
catches the A8-EXT forged-promote class; retrofit onto pattern-promote + dream-apply.
- ADR-121 provenance tiers: only oracle:test-exec evidence changes fleet behavior;
additive, conservative-backfill migration.
- ADR-122 DoE screen: model x prompt x retrieval x scaffold, run on real data
(25/27 cells, $1.25) — scaffolding (esp. reflexion) and retrieval degrade
reliability (the retort `beads` signature); simplest+cheapest stack wins.
- safe-db: AQE_DISABLE_WAL / AQE_JOURNAL_MODE env-gate (macOS virtiofs bind-mount
WAL corruption mitigation; default behavior unchanged).
Honest nulls documented: the flywheel lift is on a self-supervised proxy with the
anchor held flat; making the coupled anchor move needs harder items + a relevant
corpus (an ADR-117 re-freeze), not a retriever change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Real-time hook learning-capture was failing on this macOS Docker bind mount
with `Failed to initialize UnifiedMemoryManager: database is locked`, and a
brain-checkpoint hook was leaking deadlocked `brain export` subprocesses
(4 found, ~1.5GB RSS). Root cause is SQLite concurrency on a WAL-hostile
virtiofs mount, NOT a native-binary mismatch (better-sqlite3 loads fine).
- brain-checkpoint.cjs: add AQE_DISABLE_BRAIN_CHECKPOINT env / marker-file kill
switch (opt-in; shipped installs unaffected). The export spawns a native RVF
writer that deadlocks in a futex and ignores the SIGTERM the timeout sends,
so orphaned exporters piled up. Disabling stops the leak at the source.
- aqe-hook.cjs: make the FATAL health-log fix-hint conditional. Only suggest
`npm rebuild better-sqlite3` for real native markers; lock-contention
failures now point at the actual cause instead of sending users down the
wrong path.
- feature-flags.ts: add the missing RUVECTOR_USE_RVF_PATTERN_STORE env override
(the only RuVector flag lacking one) so an RVF FsyncFailed can fall back to
the SQLite HNSW PatternStore. Activates after build.
- scripts/aqe-db-backup.sh: consistent VACUUM INTO snapshots (safe with
concurrent writers), integrity-verified before promotion, rotating + daily,
to the host mount so they survive container loss. Restore round-trip tested.
- devcontainer.json: auto-restart the backup loop (postStartCommand) and set
bind-mount env mitigations (remoteEnv: AQE_DISABLE_WAL,
RUVECTOR_USE_RVF_PATTERN_STORE=false, AQE_DISABLE_BRAIN_CHECKPOINT).
- learning-config.json: clear the stale rebuildMode flag (no src reader; on
since 2025-12).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps package.json + package-lock + skills-manifest fleetVersion to
3.11.5. Also fixes .claude-plugin/plugin.json and
assets/skills/skills-manifest.json fleetVersion, which had drifted
stale at 3.11.0 across the last 4 releases (found via full-repo
version-string audit).
- Backup-verified cleanup of .agentic-qe/memory.db: 200/200 degenerate
mincut_snapshots rows, 501/501 degenerate mincut_history rows, 530/530
test-fixture execution_results rows, 705/705 test-fixture executed_steps
rows (all confirmed 100% junk before deleting); corrected 72
dream_insights.applied rows corrupted by the now-fixed counter bug back
to the correct boolean value. Full backup + before/after row counts +
integrity check per data-protection policy.
- Fixed 4 unused-vars lint errors in goap-planner.ts/goap-execute.ts
(2 pre-existing + 1 that surfaced after removing the first + 1 in
goap-execute.ts). Left two genuinely unimplemented stub params
(updateActionStats duration tracking, findSimilarPlan fuzzy matching)
honestly marked rather than scope-expanded.
- Filed proffesor-for-testing/agentic-qe#554 to track everything from the
system-integrity remediation that's deliberately deferred, so it isn't
silently dropped.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Three compounding bugs in the recordOutcome()/storePattern() path, found
while chasing a flaky qe_pattern_usage-count test:
- recordOutcome() wrote pattern usage twice per outcome: once via
patternStore.recordUsage() (which already persists to the wired
SQLitePatternStore) and again via an explicit direct SQLite call added
only to carry metrics/feedback (which the interface didn't accept).
Threaded metrics/feedback through IPatternStore.recordUsage() instead
and removed the redundant write — every outcome was inflating
qe_pattern_usage row counts and qe_patterns.usage_count by 2x.
- PatternStore.store() (in-memory backend) never applied the #447 fix
that RvfPatternStore already had: when ON CONFLICT(name, qe_domain,
pattern_type) preserves an existing row's id, the in-memory indices
kept using the discarded id, so every later recordUsage()/promote()/
delete() call silently failed against SQLite with "Pattern not found".
- SQLitePatternStore.storePattern() resolved the ON CONFLICT-preserved id
AFTER the insert transaction, but inserted the embedding using the
discarded id INSIDE the transaction — violating the
qe_pattern_embeddings -> qe_patterns(id) foreign key whenever a pattern
name collided with an existing row. Now resolves the actual id before
the embedding insert, in the same transaction.
- QEReasoningBank.getStats() only consulted the DB aggregate when the
in-memory counter was exactly zero, so reported totals regressed the
moment in-memory ticked past zero mid-session (a cold-start call
correctly showed the historical DB total; the next call after one
recordOutcome() dropped to reporting "1"). Since qe_pattern_usage is
written synchronously, the DB aggregate is always >= the in-memory
counter — now takes the max of the two, keeping the number monotonic.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
qe_patterns is the source of truth for pattern count and domain/tier
breakdown; the RVF/HNSW vector index only covers patterns that have
been embedded, so getStats() silently hid any pattern stored without
a matching embedding (aqe learning stats reported the vector count as
Total, and "By Domain" was hardcoded empty).
Also fixes the rvf-pattern-store.test.ts Stats test to attach an
isolated non-unified SQLite store per test — needed once getStats()
started reading real SQLite data, since the auto-attached ADR-046
unified store is a process-wide singleton shared across test files.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Full remediation of docs/analysis/SYSTEM-INTEGRITY-AUDIT-2026-07-04.md's
P0-P2 findings, tracked in docs/plans/SYSTEM-INTEGRITY-REMEDIATION-GOAP-PLAN-2026-07-04.md.
Highlights:
- Dream engine: real pattern creation on insight apply, error/outcome
concept nodes from real ADR-110 data, and a follow-up fix ensuring the
concept refresh actually runs on the real automatic path (not just via
test wrappers); persistTaskOutcome now genuinely promotes pending
insights instead of blindly incrementing an applied counter
- Witness chain: Ed25519 signing wired via persistent key directory,
archival/append-after-archival bug fixed, CI verification gate added
- Mincut: real event-bus wiring (was a no-op stub) and scaffold-vertex
detection fixes
- GOAP: real domain-API dispatch executor replacing the always-mock one
- SONA: EWC++ cold-start deadlock fixed via independent request-count
persistence
- ADR-110 pattern-nulls wired into the real production capture path
- Daemon/snapshot visibility, TTL unit bugs, and 8 ADRs re-statused with
additive verification notes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CodeQL flagged 'polynomial regular expression on uncontrolled data' in two
branch-new files:
- ollama-url.ts: trailing-slash strip `/\/+$/` backtracks O(n^2) on many
'/'. Replaced with a linear charCodeAt scan.
- pattern-cache.ts: block-comment strip `/\/\*[\s\S]*?\*\//g` backtracks
O(n^2) on unterminated '/*' (46s on a 300k adversarial input). Replaced with
a single-pass indexOf('*/') scanner.
Both are behavior-identical to the originals on all normal/edge cases (verified)
and now run in <5ms on the adversarial inputs. 14 affected tests pass; typecheck
clean. Fixes code-scanning alerts 212 & 213.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.11.4 = the local-model-improvements branch (LLM/Ollama plumbing, free-tier
local test-gen, proof-gate ADR-116) + the already-merged dependency-security
system (ADR-115). Merged origin/main in first so the release carries the
grpc-js HIGH fix and moderate-CVE reductions rather than regressing them.
Bumps package.json + package-lock + skills-manifest fleetVersion to 3.11.4.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The proof-gate work cited only upstream RuVector 'ADR-194' — which is not an
AQE in-repo ADR. Adds ADR-116 (the AQE-side integration decision: port the
hash-chain to TS, opt-in/fail-soft/single-store wiring, and why NOT to depend
on the @ruvector npm packages — backed by the verified ruvllm mock-mode/demo
findings) and cross-references it from the four source/test files that cite
ADR-194, so the in-repo decision is discoverable from the code.
Comment/docs only — no behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Runs the new `npm run deps:update` (security mode: npm audit fix
--package-lock-only) — the system applied to its own repo. Fixes the
@opentelemetry/* advisory family (W3C Baggage unbounded-memory) and bumps
the @claude-flow/* alpha chain, all within existing semver ranges.
In-repo audit: moderate 29 -> 7; high/critical stay 0.
Large diff is npm dedup: the @claude-flow/memory bump (alpha.14 -> alpha.21)
collapsed nested duplicate transitive trees (844 -> 807 lock entries).
Optional @ruvector platform deps verified intact (15/15) by the updater guard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wires the HashChainGate primitive into UnifiedMemoryManager so kv writes can
be cryptographically audited end-to-end. Design is audit-only and safe for the
production path:
- OPT-IN: off by default; enable per audit window via enableProofGate() or
AQE_PROOF_GATE=1 (the chain grows O(n) with writes, so it is meant for
bounded sync/migration/publish windows, not permanent always-on use).
- FAIL-SOFT: kvSet/kvDelete admit a content-bound receipt AFTER the row is
written, wrapped so an audit failure can never break or alter the write.
- NO RE-ENTRANCY: the chain persists via a direct write to a reserved
namespace (__proofgate__), never through kvSet, and that namespace is never
itself audited.
- UNIFIED STORE: the chain serializes into the same memory.db (kv_store), no
second store; it restores on the next process so audits survive restarts.
verifyMemoryIntegrity() re-derives the chain from genesis, turning the
"verify row counts before/after, never claim a sync succeeded without proof"
mandate into a tamper-evident guarantee. 7 tests: no-op-when-disabled,
one-receipt-per-write, reserved-ns-not-self-audited, root-advances,
persist+restore across restart, mutated-chain detection, and env auto-enable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a dependency-free TS port of ruvector-proof-gate's HashChainGate
(ADR-194): admit one tamper-evident receipt per memory.db operation;
verifyIntegrity() cryptographically re-derives the chain to prove no
admitted entry was mutated, reordered, or dropped — turning the project's
"verify row counts before/after, never claim a sync succeeded without
proof" mandate into a guarantee. Uses Node crypto only, opens no DB (chain
serializes via toJSON/fromJSON for persistence through the unified store).
7 tests mirror the Rust crate's tamper cases + a persistence round-trip.
Delivered as a primitive; NOT yet wired into live memory.db paths.
Also records the 2026-06-29 small-coder oracle measurements in
value-score.ts: qwen2.5-coder:7b=0.50 (4/8, beats general 8B at 38%) and
1.5b=0.08 — the curve motivating a PEFT-on-7B spike.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 oracle bench (8 fixtures, mutation>=60%) on the same Mac Ollama:
qwen3-coder:30b and qwen3:30b-a3b score IDENTICALLY (both 6/8, 75% avg
mutation kill, same fixtures pass/fail) — same 30B MoE class and RAM — but
the code-tuned model is ~14x faster wall-clock (5.2s vs 71.1s/gen) because
it does not spend ~70s "thinking" before answering.
Records both measurements in value-score.ts (incl. stock qwen2.5-coder:1.5b
= 1/8, confirming size still dominates coder-tuning at tiny scale). qwen3:8b
stays off-default (3/8 across the same fixtures).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds TestGenPatternCache (exact normalized-source match + cosine-similarity
tiers, injectable embedder, in-memory — no new DB, respects the unified
memory ADR) and wires it into the free-tier executor as an opt-in gate.
Safety: a cache hit is only a candidate — it is re-verified by the same
objective oracle before use, so a stale/wrong hit falls through to real
generation and can never bypass the gate. Only verified outputs are cached.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Registers qwen3:8b, qwen3:30b-a3b, qwen3-coder:30b in model-mapping
(so normalizeModelId resolves the tags) and model-registry with correct
capability flags (coder = tool-capable, non-thinking).
Adds modelSupportsTools() (fail-open on unknown ids) and a guard in the
hybrid router: when a request requires tools, candidates KNOWN to be
tool-less are skipped (with a warning) instead of silently dropping tool
definitions. Never strands a request — falls open if no candidate qualifies.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#2: single resolveOllamaBaseUrl() knob (AQE_OLLAMA_URL > OLLAMA_URL >
each call-site default) wired into all local clients — chat provider,
consensus provider, local judge, embeddings, free-tier. Unset = identical
behavior; one var now repoints every client at a remote/host Ollama.
#3: size each Ollama request timeout from num_predict and the model's
observed tok/s (EMA) instead of a fixed 120s, so slow dense/thinking
models (~15 tok/s measured) no longer silently time out mid-generation.
Explicit/configured timeouts still win.
Adds scripts/oracle-model-bench-local.ts (local mutation-oracle bench).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Close the biggest remaining drift gap (ADR-114 follow-up).
- skill-parity now gates plugins/agentic-qe-fleet/skills as a strict body-mirror alongside
assets/skills; reconcileBody + `check-skill-parity --sync` resync drifted mirrors while
preserving each tree's frontmatter (used to fix the plugins qe-quality-assessment drift)
- .kiro/skills is an intentionally divergent 86-skill variant (qe- prefixed, some large
.kiro-only bodies) — gated by PRESENCE via the conservation guard's kiro-skills surface,
not body-equality (which would destroy the divergence)
- both guards (verify:skill-parity blocking, verify:conservation non-blocking) wired into
invariant-check.yml with plugins/.kiro paths; policy doc updated
- tests: reconcileBody/splitFrontmatter covered; 16 validation tests pass
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>