Feat/forge templates - #37
Conversation
The neurobus on_tick had the same try/except block copy-pasted three times (and three duplicate imports of NEUROBUS_STATE_PATH/atomic_write_json). The first block should have written orb_state.json on every tick, but state files went stale on 2026-05-26. Consolidated into a single on_tick coroutine with two clean try blocks (lightweight neurobus_state.json + richer orb_state.json snapshot). Replaced inline __import__() calls with proper module-level imports. No change to decay rates, subscriber logic, or NCP behavior — only the duplicated write path was collapsed. After fix: orb_state.json updates every tick (1 Hz), verified by mtime and bridge /state reading real decaying neurobus values.
CodeRabbit posted two reviews against feat/bridge-query-auth covering README, web server, and neurobus. This commit resolves all actionable items. README.md: - Document AEGIS_SOCK env var (code default is /tmp/aegis.sock; the live launch uses /run/aegis/aegis.sock). - Fix intro to match architecture section: renderer chain is Groq primary with template fallback, plus Gemini where applicable. aegis/web/server.py: - Remove unused constant WS_CLOSE_POLICY_VIOLATION (never referenced). - Remove unused constant _FILENAME_RE (never referenced). - Remove redundant explicit CORS headers from SSE /logs endpoint. CORSMiddleware already injects them on all responses including StreamingResponse. Verified: ACAO, Vary, ACAC all present on EventSource handshake after removal. Sync file I/O nitpick skipped per CodeRabbit guidance (acceptable for current low concurrency; asyncio.to_thread is already used for the blocking read). aegis/nexus/neurobus.py: - Add TypeError to the except clauses around atomic_write_json calls (json.dumps can raise TypeError on non-serializable payloads; the tick loop must survive that). - Narrow the broad except Exception in _build_orb_snapshot to (ImportError, ModuleNotFoundError) for the optional imports, and add debug logging for each failure path so diagnostics are preserved. No change to decay rates, neurobus logic, or NCP behavior.
COHERENCE_UNRESOLVED = None constant was defined at server.py:59 alongside PAM_UNRESOLVED, but was never included in the response payloads. Add it to both _build_state() and /health() for symmetry with the pam field. Both are null (no runtime source — see first-contact-findings.md §11).
Persistent log of what was resolved in this session, what was deferred, and known issues for future agents. Covers: - P0 bridge endpoints (health, state, chat, logs) - Auth + CORS implementation - State-writer fix in neurobus - CodeRabbit review items resolved - Deferred items: sync I/O, docstring coverage, connected semantic - Operational issues: /run/aegis missing, leaked Groq key - Runtime gaps: pam/coherence null, tick_id not persisted
CodeRabbit posted a full bug report covering 10 issues. This commit resolves all actionable items except Bug 10 (deferred per CodeRabbit own assessment that it always reads the correct value). aegis/web/server.py: - Bug 1 (High): mkdir blocks event loop. Wrap mkdir+open in asyncio.to_thread via a _open_log helper. - Bug 2 (High): SSE client disconnect never checked. Add request.is_disconnected() in the event_stream generator so the generator exits when the browser closes EventSource. - Bug 3 (High): TOCTOU in /chat. Remove SOCK_PATH.exists() pre-check; rely on the try/except around open_unix_connection. Unify error response to socket_unavailable. - Bug 4 (High): No startup warning when HELIOS_TOKEN unset. Add log.warning in run() so operators see the misconfiguration. - Bug 5 (Medium): /health double /proc scan. Compute daemon_pid once and thread it through _daemon_uptime_seconds_for_pid(). - Bug 6 (Medium): last_action_type or chain drops valid falsy values. Use explicit _first_str() helper. - Bug 7 (Medium): CORS doesnt apply to WS upgrades. Add origin check in both state_ws and chat_ws (BaseHTTPMiddleware doesnt run on WS upgrades). - Bug 8 (Medium): _check_token type mismatch. Change signature to HTTPConnection (common base of Request and WebSocket). - Bug 9 (Low): Double time.time() in _daemon_uptime_seconds. Capture once as now. aegis/nexus/neurobus.py: - Bug 11 (Review 3 inline): Separate import guard from call in _build_orb_snapshot so a runtime ImportError inside hidden_state_vec()/pop_last_event() is not misclassified as a missing module. Also read _is_speaking as a value from the module on each call (current semantics). Bug 10 (_is_speaking reference semantics) deferred per CodeRabbit own assessment.
- Cross-reference Bug 5 fix: /health double-call correctness was already resolved by computing daemon_pid once and threading through _daemon_uptime_seconds_for_pid(). TODO retained the caching note (performance) but added a pointer to the fix. - Add ` ext language specifiers to fenced code blocks for proper markdown rendering. - Sync file I/O entry already notes mkdir is wrapped in to_thread.
Add authenticated web bridge with /state, /chat, /logs endpoints and fix stale state-writer
Comprehensive handoff document covering: - What was built (bridge endpoints, auth, CORS) - What was fixed (state-writer, all CodeRabbit reviews) - Verification results (9/9 auth tests pass) - Full commit log (10 commits) - Operator action items (merge, rotate key, fix /run/aegis) - Nice-to-haves (pam, tick_id, connected semantic, docstrings) - Live state on box (PIDs, env, tunnel, launch commands) - Pointer to full TODO.md for deferred items
Comprehensive handoff covering the complete timeline: - The original problem (no bridge, 11-day stale state) - Full bridge spec (endpoints, response shape, auth methods) - Auth implementation (token storage, validation, failure modes) - CORS journey (3 iterations, middleware + WS origin check) - State-writer diagnosis and fix - All 4 CodeRabbit reviews with resolution status - All 10 bugs from CodeRabbit report (9 fixed, 1 deferred) - Verification results - Full commit log - Operator action items (required + recommended + nice-to-have) - Live state on box with launch commands - Handoff document index
fix: chat socket retry with backoff
ci: tighten Gate 3 to block on non-APPROVED
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthrough
ChangesForge API and Panel Updates
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/components/ForgePanel.svelte`:
- Around line 106-109: The effect currently only reads $forgeDiffData when
$forgeSelectedId is null, so diff-only updates can be missed; update the $effect
callback to read both $forgeSelectedId and $forgeDiffData unconditionally (for
example by reading them into an array or using the comma operator) so that
expandedFiles is reset whenever either $forgeSelectedId or $forgeDiffData
changes; change the expression in the $effect that references ($forgeSelectedId
?? $forgeDiffData) to a form that explicitly reads both values so expandedFiles
is reliably cleared.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3c3afb12-3b76-42c2-bdca-15bd83cfe630
📒 Files selected for processing (2)
src/lib/api/forgeClient.tssrc/lib/components/ForgePanel.svelte
| $effect(() => { | ||
| void ($forgeSelectedId ?? $forgeDiffData); | ||
| expandedFiles = {}; | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Svelte 5 runes, does $effectdependency tracking include a store read on the right side of?? when the left side is non-null, or is it skipped due to short-circuit evaluation?
💡 Result:
In Svelte 5, $effect dependency tracking is based on runtime evaluation [1][2]. Because reactivity is determined by which reactive values are synchronously read during the execution of the effect function [1][3], dependency tracking follows standard JavaScript execution rules, including short-circuiting behavior [4]. If you use the nullish coalescing operator (??) in an expression like left ?? right, Svelte will skip the read of right if left is non-null [4]. Consequently, right will not be registered as a dependency for that specific execution of the effect [4][5]. If left is non-null, the effect will only depend on left; if left is null or undefined, the effect will depend on both left and right [6]. This dynamic nature means that dependencies are recalculated every time the effect runs [1][7][6]. If you require an effect to always depend on a value regardless of short-circuiting, you must explicitly read that value outside of the short-circuiting expression [4].
Citations:
- 1: https://svelte.dev/docs/svelte/$effect
- 2: https://github.com/sveltejs/svelte/blob/0c7f8151/documentation/docs/02-runes/04-$effect.md
- 3: https://svelte.dev/docs/svelte/$effect/llms.txt
- 4: docs: clarify example on dynamic dependency tracking sveltejs/svelte#13767
- 5: Svelte 5: $effect dependancy not tracked sveltejs/svelte#12743
- 6: https://www.stanza.dev/courses/svelte-5-performance/fine-grained-reactivity/svelte-5-performance-dependency-tracking
- 7: https://svelte.dev/docs/svelte/%24effect
Fix $effect dependency tracking for expandedFiles reset (diff-only changes may be missed)
On Line 107, ($forgeSelectedId ?? $forgeDiffData) short-circuits: when $forgeSelectedId is non-null, $forgeDiffData isn’t read, so the $effect won’t re-run for diff-only updates—expandedFiles won’t reset.
Suggested fix
$effect(() => {
- void ($forgeSelectedId ?? $forgeDiffData);
+ void $forgeSelectedId;
+ void $forgeDiffData;
expandedFiles = {};
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| $effect(() => { | |
| void ($forgeSelectedId ?? $forgeDiffData); | |
| expandedFiles = {}; | |
| }); | |
| $effect(() => { | |
| void $forgeSelectedId; | |
| void $forgeDiffData; | |
| expandedFiles = {}; | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/lib/components/ForgePanel.svelte` around lines 106 - 109, The effect
currently only reads $forgeDiffData when $forgeSelectedId is null, so diff-only
updates can be missed; update the $effect callback to read both $forgeSelectedId
and $forgeDiffData unconditionally (for example by reading them into an array or
using the comma operator) so that expandedFiles is reset whenever either
$forgeSelectedId or $forgeDiffData changes; change the expression in the $effect
that references ($forgeSelectedId ?? $forgeDiffData) to a form that explicitly
reads both values so expandedFiles is reliably cleared.
feat: sparse NCP wiring + urgency gate
- input_schema_v1 frozen: NeuroBus expanded 6→16 with 10 zero-fed reserve slots for future affect scalars (INPUT_DIM unchanged at 388) - New trace module (aegis/brain/trace.py) — JSONL dump of every tick: input_vec, output, intent, neurobus, text_input, tick_dt - Wire trace writes into consume_tick, best-effort (never crashes loop) - Fix stale NimNano→NimMid reference in dispatcher high-urgency filter - Enable CR watcher by default with heal loop
…c booleans, air-gap enforcement, version stamping - threat_urgency: strict monotonic -> Spearman rho + top-quartile - listens: absolute epsilon -> variance ratio vs all-constant baseline - n_tick_memory: fixed 0.8 threshold -> cosine margin vs distractor baseline, N sweep - calibration: no-op -> Spearman rho(confidence, correctness) > 0.4 - ablation: hard gate (never averaged), measured on eval output delta - Predicate API: per-item -> full-batch (outputs, **kwargs) -> list[bool] - Air-gap: EVAL_SEED_NAMESPACE (9000-9999), _assert_eval(), compositional_holdout - Version stamp: md5(seed:name)[:8] for regression corpus tracking - SpecReport: per-spec booleans, is_hard_gate, no aggregate averaging - ncp-reasoning.md: added section 7.6 hardening notes
ncp.py: consume_tick waits for _MEM_EVENT before publishing intent retrieve.py: seed facts placed first in candidate list write.py: added T2 fact extraction after user turn storage cr_watcher.py: end-to-end CR polling with Supabase forge task creation server.py: .env auto-loading for daemon and bridge event.schema.json: cr_watcher source + CR event types
… ρ, horizon reporting - listens reclassified as precondition/liveness gate (not behavioral) - compositional_holdout uses Spearman ρ(threat, urgency) instead of urgency>0.5 (isolates threat→urgency reflex; floor now ~0%, not 76.6%) - threat_urgency drops redundant top-quartile; ρ > 0.8 alone - n_tick_memory reports memory_horizon (largest N with margin > 0.15) as metrics - SpecDataset.is_precondition flag; behavioral_specs() and preconditions() methods - SpecReport tracks each spec individually with metrics; no pooled average - Precondition failure → abort eval (wiring broken)
…ose (CfC monotonic activations produce ρ≈1 even untrained). Top-quartile > 0.5 is meaningful: urgency [0,1] midpoint is the action gate threshold. Floor confirmed 0.0%.
19bbe43 to
afaab7e
Compare
Task templates, diff view improvements, type contract fixes
Summary by CodeRabbit
Bug Fixes
Improvements