dev: reh3376_dev01 -> main#452
Conversation
…Prometheus datasource
The Epic 6 panel used datasource {type: prometheus, uid: prometheus} but
this Grafana instance has no Prometheus datasource configured — mdemg
exposes counters as JSON via /v1/metrics/snapshot, not a /metrics scrape
endpoint. Configured datasources: mdemg-nodegraph, neo4j, timescaledb
only. The panel rendered "No data" in the live Grafana.
Rewritten panel queries the reinforcement_events hypertable directly via
the timescaledb postgres datasource. Two targets:
1. count(*) over 1-minute time_buckets → overall events/min
2. count(*) FILTER (WHERE created_new_edge) vs WHERE NOT created_new_edge
→ split between new connections formed and existing connections
strengthened (the operational dimension the analytic queries
actually need)
Both targets templated on $space_id (existing dashboard variable). The
Prometheus counters (mdemg_eventgraph_writer_rows_{enqueued,dropped,
flush_failure}_total) remain wired and incrementing — they surface via
/v1/metrics/snapshot for ops scripts. The Grafana panel now actually
displays data instead of relying on a scrape path that doesn't exist
in this deployment.
Discovered during post-merge live verification (2026-05-29). Verified
fix: reloaded dashboard via Grafana API → /api/ds/query against same
SQL returns 1-minute buckets matching TSDB direct count. Audit harness
now reports 2 PASS for the new panel (previously SKIP — no SQL target).
verification.md updated with the post-merge transcript.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
# Conflicts: # deploy/docker/grafana/dashboards/mdemg-graph-topology.json # docs/development/eventgraph-001/verification.md
P0 fix. The Jiminy guidance->feedback->outcome loop has been dormant ~9 weeks: consulting/service.go gates constraint/suggestion extraction on hardcoded legacy-scale score thresholds (r.Score < 0.55 et al.). Phase 13.1 RRF (default-on May 3) dropped the score scale so strong matches top out ~0.53 -> 0/10 results clear the gates -> empty guidance -> dead loop. Third instance of the RRF-score-contract bug class (after the EVENTGRAPH-001 Activation drop). 12-section format; 6 epics; config-driven percentile-gate fix + sigmoid recalibration; live-verify the revived loop end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Full-repo sweep of post-RRF score/activation/confidence consumers + live score-distribution sampling. Findings: - HIGH (4): consulting constraint gates (1005/1081/1087) + confidence sigmoid midpoint 1.5 (35-36) — the loop-killer cluster. - MED (5): consulting conflict gates (931/944/957/981) + minConfidence pre-filter (619, already config-driven). - LOW (3): retrieval/jiminy.go Activation display gates (45/155/192) — explanation text only, no guidance gating. - NONE (2): jiminy trial score (0-10 scale), trust-score clamp. Live distribution: RRF strong-match top scores cluster 0.49-0.58; the 0.55 gate sits mid-band, rejecting the most-relevant constraint half the time. NormalizedConfidence is positional rank (spreads 100->0 even on uniform-score sets) -> rules out plan Option A (percentile) as sole gate. Remediation: config-driven RRF-calibrated absolute thresholds (Option B), constraint floor default 0.45, sigmoid midpoint ->0.45. Disclosed deviation per feedback_plan_options_pattern. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…SCALE-001 Epic 2)
Revives the dormant Jiminy guidance loop. Replaces 7 hardcoded legacy-
scale score gates in consulting/service.go + the score->confidence
sigmoid (both copies) with config-driven, RRF-calibrated values.
Gates (all default 0.45, RRF strong-match band is 0.49-0.58):
- constraint extraction (was <0.55) -> CONSULTING_CONSTRAINT_SCORE_FLOOR
- keyword/name authority inner gate (0.55/0.6) -> CONSULTING_AUTHORITY_SCORE_FLOOR
- conflict/contradiction detection (0.6-0.7) -> CONSULTING_CONFLICT_SCORE_FLOOR
Key Epic-2 finding: keywordClassifyConstraint has an INNER authority
gate that binds tighter than the outer constraint gate. If authority
floor > constraint floor, the binding gate re-rejects the strong-match
band and the loop stays dormant -> all three default to 0.45. The RRF
band is too compressed to subdivide into tiers; knobs stay separate so
operators can raise any one independently.
Sigmoid (score->confidence), both consulting/service.go and
jiminy/retrieval_source.go (they MUST stay in sync per their own
comments): midpoint 1.5 -> 0.45, steepness 1.5 -> 8.0, config-driven via
RETRIEVAL_CONFIDENCE_SIGMOID_{MIDPOINT,STEEPNESS}. Legacy crushed a
strong 0.5 match to 0.18 confidence; recalibrated maps it to 0.60
(0.1->0.06, 0.58->0.74). normalizeRetrievalConfidence is now a Service
method reading cfg with zero-value fallback; mapRetrievalToGuidance
takes the sigmoid params from its caller's cfg.
5 new config knobs, all with RRF-calibrated defaults + zero-value
guards (no-hardcoding rule; the bug WAS a hardcoded value).
Tier 1 tests: updated 2 legacy-scale boundary tests to the new
thresholds + added RRFStrongMatchBand regression (0.50 must surface),
ConstraintFloor_ConfigDriven (override honored), and
NormalizeRetrievalConfidence_RRFCalibration (band mapping). Full
consulting + jiminy + config suites green; lint clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
retrieval/jiminy.go Activation display gates (45/155/192 + LearningEdge siblings) traced live: they're in the explainability renderer, not the guidance-surfacing path; always-additive at RRF scale (live activation ~0.723 >> thresholds), no misbehavior. Intentionally left unchanged with rationale — config-ifying display verbosity is out of proportion to zero functional impact. Every High/Med remediated (Epic 2), every Low decided. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pic 4) Tier 3 live e2e (verification.md): the score-gate fix revives the dormant guidance loop on the live stack — - /v1/jiminy/guide guidance items 0 -> 10, source_counts.constraints 0 -> 2, patterns 0 -> 3 (acceptance #1 MET). - Full loop warm->latest->feedback->outcome: TSDB constraint_outcomes sink REVIVED — fresh rows dated 2026-06-03 (table was dead since May 1). Constraint-effectiveness Grafana sink is live again. Three adjacent issues surfaced during live smoke, documented as distinct follow-ups (NOT score-scale, not bolted on): - A: Neo4j GUIDANCE_OUTCOME edges still dormant — guidance SourceNodes point at emergent_concept nodes; PersistGuidanceOutcome only writes edges for constraint/correction/pattern/learning or role_type= constraint targets. Node-type-targeting bug, independent of RRF. Candidate sprint JIMINY-OUTCOME-001. - B: LLM guidance synthesis timeout (now that synthesis runs). - C: /v1/jiminy/latest unescaped control chars break jq/json parsers — the hook uses jq, so may compound dormancy. Low-effort follow-up. Tier 2 (rrf_scale_guidance_test.go, integration tag, 2 green): - SuggestSurfacesGuidance: constraint-matching context surfaces 7 suggestions (was 0 before fix) against live mdemg-dev. - SuggestRejectsNoise: gibberish does not flood constraints (no over-correction). Cold-start note: first guide call post-restart returned constraints:0 (LLM classifier cold-model timeout -> keyword fallback); after one warm-up call, constraints surface. Model-warmth artifact, not a fix defect. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t.md (Epic 5) Final epic. CHANGELOG Unreleased gains the RRF-SCALE-001 Fixed entry. CLAUDE.md gains a 'score-scale contract' architecture note — the structural defense against a 4th instance: downstream consumers MUST NOT hardcode absolute thresholds against RetrieveResult.Score (the scorer scale is not a stable contract); gate via config or a scale-invariant signal, and re-audit on any scorer change. Notes that NormalizedConfidence is positional (not a safe sole gate) and records the three open follow-ups. post.md: epic-by-epic, acceptance check-off (honest: #2 partial — TSDB sink revived, Neo4j edge is distinct Follow-up A), scope note separating the score-scale fix (done) from the 3 adjacent surfaced issues (documented follow-ups), discipline notes (cold-start mask, inner authority gate). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ment (CI fix) CI failure on PR 404: TestRRFScale_SuggestSurfacesGuidance failed in 0.02s. Root cause: the test assumed the populated local mdemg-dev space (111 constraint nodes), but CI boots a FRESH EMPTY Neo4j with stub embeddings (and RETRIEVAL_COLUMN_VOTING_ENABLED=false / legacy scorer). With no data, /v1/memory/suggest returns 0 candidates, so the 'total == 0' assertion fired. Other integration tests self-seed data or skip when prerequisites are absent; mine relied on ambient data — wrong for a reproducible CI run. Fix: skip when debug.retrieved_count == 0 (no retrievable data → the score-gate fix isn't exercisable; there's nothing for the gate to admit or reject). The test stays meaningful against a populated stack (local: 9 suggestions from 15 retrieved → PASS) and skips cleanly in CI's empty-DB environment. Verified both paths live: populated → PASS, empty space → retrieved_count 0 → SKIP. The gate fix itself is validated by Tier 1 unit tests + the live Tier 3 e2e (docs/development/rrf-scale-001/verification.md); this integration test is a bonus live-stack assertion, not the primary proof. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… sink Follow-up A from RRF-SCALE-001: the Neo4j GUIDANCE_OUTCOME edge sink has been dormant since Apr 12. Root cause: matchConstraintCode links guidance items to constraint codes by keyword overlap (>=3 shared words), but retrieval surfaces emergent_concept abstractions whose content does not share 3+ literal words with raw constraint text -> no constraint_code -> PersistGuidanceOutcome falls back to the concept SourceNode -> the role_type=constraint filter rejects it -> no edge. Live-proven: all 17 recent outcome rows had constraint_code=(none). Fix (Option 1): switch the matcher to embedding cosine similarity (content already normalized to natural language ~0.70 cosine; Service has an embedder; cosineSimilarity + embed->cosine pattern already exist in-package via OutcomeClassifier). Existing PersistGuidanceOutcome + findConstraintNodeID then create edges on the correct constraint nodes. Keyword matching stays as fallback -- never regresses. 4 epics; ~1-1.5 dev-days; config-driven threshold; acceptance bar = a fresh Neo4j GUIDANCE_OUTCOME edge on a real role_type=constraint node dated today, reflected in GetConstraintEffectiveness. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…UTCOME-001 Epic 1) Revives the Neo4j GUIDANCE_OUTCOME edge sink (dormant since Apr 12). Root cause (RRF-SCALE-001 Follow-up A): matchConstraintCode links guidance items to constraint codes by keyword overlap (>=3 shared words), but retrieval surfaces emergent_concept abstractions whose content rarely shares 3+ literal words with raw constraint text -> no code -> PersistGuidanceOutcome falls back to the concept SourceNode -> the role_type=constraint filter rejects it -> no edge. Fix: new matchConstraintCodeByEmbedding queries the constraint vector index (db.index.vector.queryNodes, role_type=constraint, sim >= threshold) and returns the closest constraint's code. Guide() tries this first, falling back to the keyword matcher when the embedder is unavailable, content is empty, or nothing clears the threshold — never regresses. The existing PersistGuidanceOutcome + findConstraintNodeID then create the edge on the correct constraint node. Implementation refinement vs plan: uses Neo4j's vector index server-side (mirrors the proven Evaluator.findMatchingConstraints pattern) rather than loading all constraint embeddings into Go and computing cosine in a loop — cleaner, no constraintCodeEntry.Embedding needed. Same Option-1 outcome. Config: JIMINY_CONSTRAINT_CODE_SIM_THRESHOLD (default 0.55, zero-value fallback) — provisional; tuned against the live similarity distribution in Epic 2. Tier 1 (4 tests): nil-driver/empty-embedding guards, threshold default resolution, keyword-fallback non-regression. Full jiminy + config suites green; lint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…on (Epic 2)
Tier 3 live e2e (verification.md) — acceptance bar MET:
- /v1/jiminy/guide now yields guidance items carrying constraint_codes
(10 items, 6 coded; was 0). Matched code 'no-direct-main-commits' is
semantically exact for the 'commit to main' context.
- Full warm->latest->feedback loop: Neo4j GUIDANCE_OUTCOME 893 -> 899
(+6), latest today. All 6 new edges land on REAL role_type=constraint
nodes ('CONSTRAINT: NEVER commit directly to main') — not
emergent_concept. The sink dormant since Apr 12 is revived on the
correct nodes.
- /v1/constraints/effectiveness reflects it: 'NEVER commit directly to
main | surfaced: 30 followed: 28 rate: 0.93'.
- Both sinks now revived: TSDB (RRF-SCALE-001) + Neo4j (here). The
constraint-effectiveness loop is fully restored.
Threshold 0.55 validated live: correct matches, no false positives.
Tier 2 (jiminy_outcome_test.go, integration tag, skip-on-empty): PASSES
on a populated stack with an idle LLM (7/10 items coded). The guide path
is LLM-latency-dependent (per-node classifier ~31s/call, serialized; a
call fired while the LLM is busy fast-fails empty), so the test
warm-retries and SKIPS (never false-fails) when the LLM path can't
produce items. Bonus check; Tier 3 is the definitive proof. The LLM
serialization/synthesis-timeout is RRF-SCALE-001 Follow-up B, tracked
separately.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Final epic. CHANGELOG Unreleased gains the JIMINY-OUTCOME-001 Fixed entry. CLAUDE.md gains a guidance-outcome constraint-code-matching note (embedding-first via vector index, keyword fallback; both outcome sinks now live). post.md: epic-by-epic, acceptance check-off, the loop-revival completion (TSDB from RRF-SCALE-001 + Neo4j here), discipline notes (LLM serialization is the test-flakiness source), forward-looking (Follow-up B now the most operationally-visible remaining issue). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t (Follow-up B) Synthesis fails on every production warm call (6/6 jiminy.synthesize errored). Root cause: the hook's /warm path runs background Guide() with a hardcoded 30s timeout (handlers_jiminy.go:302), inside which the per-node constraint classifier runs SERIALLY (~1.5s x ~10 nodes ~= 15s), leaving only ~15s for synthesis which needs 8-27s -> deadline exceeded. JIMINY_TIMEOUT_MS=240s is configured but the 30s hardcode caps it. Fix (both): (1) parallelize the per-node classifier with bounded concurrency (CONSULTING_CLASSIFY_CONCURRENCY, default 4 matching llama-server --parallel 4); (2) config-drive the warm timeout (JIMINY_WARM_COMPUTE_TIMEOUT_MS, default 90s). Acceptance: synthesis succeeds live (no synthesis_error), measured latency drop, no constraint-surfacing regression. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…E-SYNTH-001 Epic 1) The per-node LLM constraint classifier in findApplicableConstraints ran serially (~1.5s/node x ~10 nodes ~= 15s), starving guidance synthesis of its time budget (synthesis 6/6 errored on the warm path). Now classifies with bounded concurrency. - Gate-first (RRF-SCALE-001 score floor) to fix a stable candidate order, then classify each candidate into a position-indexed slot via a semaphore-bounded worker pool, then collect-in-order + dedup-by-name — output is identical to the serial path (determinism). Keyword-only (no LLM) or cap=1 runs serially (no LLM latency to hide). - Config: CONSULTING_CLASSIFY_CONCURRENCY (default 4, matching llama-server --parallel 4; floor 1 = serial rollback). Zero-value fallback to 4. - Extracted constraintClassifierIface (minimal Classify surface) so the concurrent path is unit-testable with a fake; *ConstraintClassifier satisfies it; SetConstraintClassifier guards against a typed-nil interface. Tier 1 (5 new, -race clean): ParallelEqualsSerial (determinism + order), ParallelIsFaster (concurrency overlaps latency), ErrorFallsBackToKeyword (fallback intact), ScoreGateStillApplies (RRF-SCALE-001 gate preserved), ConcurrencyDefaultFallback. Existing findApplicableConstraints tests unchanged — no regression. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pic 2) The warm-path background Guide() ran with a hardcoded 30s timeout (handlers_jiminy.go:302) even though JIMINY_TIMEOUT_MS=240s is configured. 30s was too tight for the per-node classifier (~15s) + synthesis (8-27s) -> synthesis deadline-exceeded every warm call. Replaced with JIMINY_WARM_COMPUTE_TIMEOUT_MS (default 90000, zero-value fallback 90000) — headroom for the now-parallel classifier (~7.5s) + a slow 27s synthesis. No-hardcoding rule. Rollback: set to 30000. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Epic 3)
Tier 3 live e2e (verification.md): the warm production path now produces
a synthesized narrative — synthesis_used=true, no synthesis_error,
1892-char augmentation. Fresh jiminy.synthesize succeeded at 50.7s
latency (fit the new 90s budget; would die at the old 30s — validates
the default). Both fixes needed.
Tier 2 (guidance_synth_test.go, integration, skip-on-empty + LLM-
tolerant): PASS — warm path produces guidance without synthesis_error.
Docs: CHANGELOG Fixed entry; CLAUDE.md guidance-synthesis-budget note
('when adding LLM calls to the guidance hot path: respect the
warm-compute budget and prefer bounded concurrency over serial loops');
post.md with the data-driven diagnosis + forward-looking (Follow-up C
now the last open item).
Closes Follow-up B. The guidance pipeline (surfacing + codes +
synthesis) is fully functional end-to-end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow-up C (the last open item from RRF-SCALE-001 triage) investigated and closed with evidence — NO code change, because there is no bug to fix. The earlier /v1/jiminy/latest parse failures were client-side shell artifacts (co-occurring with the session's 'failed to change group ID' errors + ad-hoc variable-capture piping), not server bytes: - writeJSON uses json.NewEncoder().Encode (encoding/json always escapes control chars U+0000-U+001F); no raw-write bypass; no custom MarshalJSON. - The synthesized narrative is double-StripControlChars'd (synthesizer.go :127 + service.go:1116). - prompt-context.sh already strips control chars via perl before jq, with 2>/dev/null + // empty fallbacks. Live-verified: the hook's exact jq returns guidance_id correctly; 5 rapid /latest fetches all parse as strict-valid JSON; 0 raw control chars. Per 'don't fix a non-problem', shipping a fix would invent a bug that doesn't exist. Closure documented in docs/development/followup-c-closure.md. This closes the entire RRF-SCALE-001 follow-up triage: A (JIMINY-OUTCOME -001), B (GUIDANCE-SYNTH-001), C (non-issue). The guidance->feedback-> outcome loop is fully functional end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ts (GUIDANCE-SYNTH-001 fix-commit) Two things, both from a live e2e of the full loop through the real production hook path (run per user directive: standard tests don't find live problems). 1. Sibling bug: the /v1/jiminy/guide handler had the SAME hardcoded 30s cap as the warm path (handlers_jiminy.go). GUIDANCE-SYNTH-001 fixed warm; /guide still deadline-exceeded synthesis at exactly 30.003s (this is what made prior sprints' /guide integration tests flaky). Now uses the config-driven budget. Live-verified: a 50.05s synthesis completed (synthesis_used=true) — would die at 30s. 2. Single source of truth for config defaults (user directive: 'single place to change all instances'). The 90s budget was duplicated as a literal in 3 sites; prior sprints similarly duplicated each default (the sigmoid 0.45/8.0 was in 3 places). Now each default is one exported config.Default* const, referenced by FromEnv and aliased by consuming-package fallbacks + a Config.JiminyWarmComputeTimeout() method. Consolidated: warm-compute timeout, the 3 consulting score floors, sigmoid midpoint/steepness, constraint-code sim threshold, classify concurrency. Zero behavior change (compile-time aliases); -race + full suites green. Live e2e also re-confirmed: real hook captures guidance_id -> feedback -> +7 Neo4j GUIDANCE_OUTCOME edges on real constraint nodes + 10 TSDB rows (whole loop closes through the actual hook; re-confirms Follow-up C non-issue). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…S backfill Builds the first consumer for EVENTGRAPH-001's reinforcement-neighborhood federation API (which has no consumer): a 'mdemg eventgraph' CLI command. Validates the Pattern Y1 bet + becomes the live-testing harness for EVENTGRAPH-002/003 (user directive: build the consumer first). Per the UxTS directive: maps the work to the frameworks. UATS applies to the federation HTTP API -> add eventgraph_reinforcement_neighborhood.uats .json (backfilling the -001 gap; the endpoint shipped with no UATS), which replaces an ad-hoc Go integration test as the Tier 2 contract test. UVTS/UBENCH N/A. UOTS panel-spec gap noted as a follow-up (out of scope). CLI rendering -> Tier 1 Go units. 4 epics; CLI (--seed/--query/--hops/--since/--limit/--json) renders summary + events table or JSON; server-driven defaults (no re-hardcoding); read-only. ~1-1.5 dev-days. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… (Epic 1) First consumer of the EVENTGRAPH-001 federation API — POSTs to /v1/eventgraph/reinforcement-neighborhood, renders a summary + events table (or --json). Supports --seed, --query (resolves seed via /v1/memory/retrieve top-1), --hops, --since, --limit. Unset flags are omitted from the request so the server applies its config defaults (no re-hardcoding of hops/since/limit in the CLI). Registered under the "advanced" command group. Tier 1 (httptest, -race clean): request-mapping omit-when-unset + conversion, --query seed resolution, no-results + invalid --since + surfaced-503 errors, render (empty + table), helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…y neighborhood
Caught in EVENTGRAPH-CLI-001 live contract testing (standard code tests
missed it; the live UATS happy-path against the running server did not):
walkNeighborhood returns a nil slice when the seed has no neighborhood
(e.g. an unknown seed), which JSON-marshals to `null`, while Events is
defensively initialized to []. Both are array fields and must serialize
consistently — null breaks any consumer asserting an array type (incl. the
new UATS contract's `type_is array` on $.neighbor_node_ids).
EventsInGraphNeighborhood now coalesces the nil slice to []string{}.
Tier 1 TestFederationResult_EmptyArraysNotNull pins the JSON contract.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Backfills the UATS gap EVENTGRAPH-001 left (no contract test for /v1/eventgraph/reinforcement-neighborhood). 6 cases, validated 6/6 live against the running server: - happy 200: asserts the response contract shape (events/neighbor_node_ids arrays, graph_hops/tsdb_rows_scanned numbers, truncated boolean) — robust to data, works even with an unknown seed (empty neighborhood is valid 200) - missing_space_id / missing_seed_node_id → 400 (empty-string override, since the runner deep-merges variant body over base — key omission can't unset) - negative_hops → 400, hops_over_ceiling (999 > 2×default) → 400 - method_not_allowed (GET) → 405 sha256 integrity hash added + verified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… + close (Epic 3) Tier 3 live e2e verified the real binary against the real stack: --query surfaced 20 reinforcement events in a 5-node neighborhood (demonstrating the Hebbian-write → federation-read loop closing in one command); --seed/--json/ --limit/unknown-seed/no-arg paths all verified live. Feature doc gains the CLI consumer section; CHANGELOG Added + Fixed entries; CLAUDE.md architecture note; verification.md + post.md (UxTS mapping: UATS done, UOTS follow-up carried over). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…TSDB CI Test failed: the UATS contract step boots a minimal server without TSDB, so the eventgraph service is nil and every POST returns 503 "service not initialized" instead of the expected 200/400 (only GET→405 passed, since the method check precedes the service check). Same class as PR #404. The federation endpoint genuinely requires TSDB (it queries reinforcement_events; the service is nil without TSDB at boot), and CI's UATS step already excludes `tsdb`-tagged specs (ci.yml --exclude-tag ...,tsdb). Added "tsdb" to api.tags (matching metrics_snapshot/readyz_tsdb); re-hashed. Verified locally: the spec now reports Status: skip under the exact CI exclude filter, and still 6/6 live against the full stack via explicit --spec. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… closed (Epic 6) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… reh3376_dev01
1. compose LLM_ENDPOINT default 8101→8102 + stale Phase-11.6 comment (triple-confirmed audit finding; un-overridden Docker deployments pointed at the port decommissioned 2026-05-03; both copies, parity ok) 2. 00_README_v2.md version ledger unfrozen: v5.13 catch-up entry (13.5 cutover, MODEL-DIST-001/002, FT-RECURSIVE-000, FT-CLASSIFY-002) — append-only, R-LT-4-clean 3. README dashboard tab count 8→10 4. pre-campaign-checklist schema v8+→26 (cites config.go as authority) 5. beta-testing version-under-test marker → v0.10.1 6. live-validation F11 framing verified already-correct (no change) + CHANGELOG entry for 001a (rides dev01 per charter carve-out) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…that can fire Live baselines escalate the roadmap's diagnosis: the surprise chain is flat DEAD, not noisy — all 221,504 reinforcement events ever carry surprise_factor=1.0; node surprise_score avg 0.023 (max 0.503, n=5,808) vs hardcoded 0.4/0.7 thresholds. Scope: vector-index top-K novelty + config-driven thresholds recalibrated to the new scale in the same sprint (RRF-SCALE lesson) + CoactivateSession surprise-CASE audit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ty (Epic 1) Replaces the unordered LIMIT 50 sample (no ORDER BY) whose comparison set was dominated by EMPTY-ARRAY embeddings — 4,564 of 5,810 conversation observations (78%) carry size(embedding)=0, passing the old IS NOT NULL guard while cosine() yields NULL; this is why node surprise_score averaged 0.023 and every reinforcement event ever carried surprise_factor=1.0. New: exact ORDER BY cosine scan over real-embedding (size=dims), non-archived, space-scoped conversation observations; config SURPRISE_EMBEDDING_NOVELTY_TOPK (50) + _SIM_FLOOR (0=off). The db.index.vector.queryNodes route was live-REJECTED: the label-wide index is crowded by ~100k non-conversation nodes (top-200 near a conversation seed were ALL emergent_concept centroids — the HIDDEN-CHURN degeneracy), pruning role-filtered hits to zero; the exact scan over ~1.2k real rows is deterministic and ~ms (revisit at ~50k). Live-verified: avg sim 0.680 / count 50 over the true nearest set. Follow-up recorded: the 78% empty-embedding backlog (embeddings backfill) is its own item. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… at both Cypher sites (Epic 2) CoactivateSession DOES compute the surprise CASE (audit result) — the chain was dead purely from broken scores. The hardcoded 0.7/0.4 thresholds (unreachable: live max score 0.503, avg 0.023 under the old noise) become SURPRISE_FACTOR_HIGH_THRESHOLD (0.5) / SURPRISE_FACTOR_MEDIUM_THRESHOLD (0.3) — defaults calibrated to the exact-top-K novelty scale, parameterized into BOTH ApplyCoactivation and CoactivateSession Cypher (never recalibrate against the old scale — the RRF-SCALE lesson). Non-positive config falls back to defaults. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…loud error path (Epics 3-4) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ace/outcome split, token floors (Epics 1-3)
Budgets: JIMINY_TIMEOUT_MS default 15s→0 (=derive from the 90s
warm-compute budget — both paths run the same synthesis work; the
independent 15s starved every fresh install, the GUIDANCE-SYNTH-001
class); /reformulate's hardcoded 10s → JIMINY_REFORMULATE_TIMEOUT_MS
(0=derive); config.Validate() warns on explicit budget incoherence.
Attribution: PersistGuidanceOutcome now receives feedbackSessionID
(was literal "" — every GUIDANCE_OUTCOME edge ever has null
session_id; forward-only fix). Surface-vs-outcome split:
mdemg_jiminy_guidance_surfaced_total{space_id} (the honest denominator
— TotalGuidanceIssued only counts guidance that RECEIVED feedback) +
mdemg_jiminy_feedback_dropped_total{space_id} on tracker-expiry drops.
Floors: JIMINY_OUTCOME_LLM_MAX_TOKENS 100→3000 (truncation risk on the
classifier reasoning field → parse fail → heuristic fallback, the
JIMINY-OUTCOME-002 artifact class), SYNTHESIS 2000→3000, EVALUATE
2000→3000 (standing ≥3000 rule; completion stops at JSON end — floors
are free insurance). Stale TTL comment fixed (1800→86400 actual).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…keleton (Epic 1a) scripts/verify_route_consumers.py extracts the live route table and fails on bidirectional drift (unlisted route / stale entry) and on any UNREVIEWED disposition — the bootstrap marker. Gate verified failing on the 187 fresh UNREVIEWED entries; adjudication next. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cking CI gate (Epic 1b) All 187 routes carry evidence-based dispositions: 109 ACTIVE, 60 OPERATOR_SURFACE, 13 INTERNAL, 4 PRUNE_CANDIDATE, 1 DEFERRED. 171/187 matched to UATS specs. Orchestrator re-verified every PRUNE_CANDIDATE and known false positive independently. Census reversals vs recon (the false-positive class this gate exists to catch): /viz/topology + /api/graph/* are LIVE Grafana consumers (topology iframe + nodegraph datasource) — removed from the prune list; /v1/conversation/snapshot* is NOT called by pre-compact.sh (saves via /v1/conversation/observe) — OPERATOR_SURFACE. Hidden consumer surfaced: embedded /ui/ dashboard consumes ~35 routes that look dormant from hooks/CLI/scripts alone. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… ordering (Epic 2) The Hebbian signal learner (V0024 SignalState, supervised flush, startup hydration, live emission/response stream since HOOKWIRE-001) had a read side with ZERO production callers. Guide() now orders within equal priority by (1-w)·confidence + w·GetStrength(code), w = JIMINY_SIGNAL_STRENGTH_WEIGHT (default 0.2; 0 = off, pre-census behavior; clamped to 1). Ordering only — selection/filtering untouched. Unknown codes blend the learner's 0.5 neutral default. 6 Tier 1 tests pin the contract: weight-0/nil-learner pure confidence, blend formula, neutral default, clamp, priority dominance + within-priority strength overtake. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ic 3) Pruned (each independently re-verified zero producers + named successor): - /v1/feedback — gap-feedback intake; live channel is /v1/jiminy/feedback. Handler + isolated gaps.ProcessFeedback/Feedback removed. - /v1/memory/ingest-codebase[/] — deprecated since Phase 94 (Deprecation header); successor /v1/memory/ingest/trigger. Whole handler file removed. - POST /v1/alerts/grafana — superseded by the native alert evaluator; only ref was a commented-out contactpoint. Compose env MDEMG_GRAFANA_ALERT_WEBHOOK_URL removed from both compose files. NOT pruned (census reversals): /viz/topology + /api/graph/* are live Grafana consumers; PREDICTS/FORESHADOWS exist nowhere in code (recon claim was wrong — no-op). 6 UATS specs removed + capability_gaps_full /v1/feedback variants dropped; UXTS matrix 220→214; inventory entries retained as PRUNED with removed_in. Gate: 183 live / 187 inventoried, OK. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bserves Live-smoke catch (DORMANT-CENSUS-001 Tier 3, own fix commit per precedent): ConstraintCodeGenerator.GenerateCode's collision branch called fallbackCode while holding g.mu; fallbackCode locks g.mu again. sync.Mutex is not reentrant — the first LLM-returned code that collided with a registered code deadlocked the generator permanently, and every later constraint-typed /v1/conversation/observe queued behind it forever (UATS conversation_observe_pinned hung 45-90s+ deterministically; goroutine dump showed the holder 18 min wedged at codegen.go:121 with N waiters at :47). Fix: fallbackCodeLocked (caller holds g.mu) used by the collision branch; fallbackCode wraps it. Regression test drives the real collision path through a fake OpenAI-compat endpoint with a 10s deadlock tripwire + post-call usability check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sprint DORMANT-CENSUS-001 — The Standing Dormancy GuaranteeThe FINAL committed Q3 roadmap sprint. The quarter's bug classes (24-day Hebbian no-op, 9-week guidance dormancy, dead actuators, zero-write tables, flat-dead surprise chain) share one shape: a surface with no consumer, invisible until someone looks. The looking is now CI. Epic 1 — Route↔consumer inventory + merge-blocking gate (
|
…variant removal The Epic 3 prune removed the spec's two /v1/feedback variants but did not re-pin its integrity sha256 — the merge-blocking UNTS hash-verify step correctly caught the drift on PR #452. 214/214 valid locally. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Development branch changes from
reh3376_dev01.Commits
mdemg modelCLI + pluggable Fetcher interfaceAuto-generated PR from reh3376_dev01 push