Fix local-only picker still skipping on a genuinely fresh enroll (issue #281 follow-up)#286
Conversation
#281 follow-up) After the #283 reordering the picker ran at the right time but queried through the wrong registry: hyp remote login boots its kernel at dispatch time, before enrollment, and on a first-run box the local config names no plugins. The login process's query-registry snapshot therefore never registers ai_gateway_messages - that registration arrives with @hypaware/ai-gateway, which the org config-control pull enables only after enrollCentralSink installs the daemon. listCapturedDirectories then failed with "unknown dataset" (best-effort null), waitForCapturedDirectories read null as "enumeration cannot run, stop now" (no 30s poll), and the picker took its enumeration_failed durable-hint path on exactly the fresh enroll it exists for. The #283 tests stubbed waitForCaptured/listCandidates, so the gap was never exercised; a re-login on a populated box worked, which is why manual verification passed. Fix: freshenCaptureEnumeration (src/core/cli/remote_commands.js). On the fresh-enroll interactive fork, after waitForClientAttach returns a client, re-boot one fresh kernel (config profile, the same layered resolution any subsequent hyp command runs) and hand its registry's enumeration to the capture wait. One re-boot is sufficient by construction: attach markers are written by the reconciler that runs only after a confirmed config apply, so attach means the pulled central layer is on disk - and the attach handler requires the gateway capability, so that layer enables the plugin. The snapshot-already-has-it case (re-login on a populated box) skips the boot entirely; a failed re-boot or a still-missing dataset falls back to the prior behavior. Best-effort throughout: the refinement never breaks the login it refines (LLP 0072). The handle is disposed (sources.stopAll, mirroring dispatch) after the picker so no boot-started source keeps the login process alive. local_only.js exports CAPTURE_DATASET so the registry check and the enumeration SQL cannot drift. LLP 0069/0080 carry forward-ref notes per the immutable-record convention. Tests: seam-level coverage of the refresh wiring (fresh enumeration is polled, disposed after the picker; null refresh falls back), unit coverage of freshenCaptureEnumeration (snapshot no-op, success, still-missing, boot-throw), and - the #283 lesson - one deliberately unstubbed test that runs the REAL bootKernel against an on-disk central layer naming @hypaware/ai-gateway and asserts enumeration RUNS (empty list, pollable) instead of failing to null. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
neutral review — adopted PR (full-heal), head Verdict: clean. No blockers or majors; one theoretical minor noted below (no action required). Mergeable ∧ green (typecheck + test both SUCCESS) ∧ reviewed. What it does: On a genuinely fresh enroll, Correctness:
Test quality: Genuinely reproduces the bug and is not vacuous. Five DI unit tests cover every branch; the real- @ref: New Minor advisory (no action): |
|
neutral verdict: approved ✅ — mergeable ∧ green ∧ reviewed at head |
Problem
After #283 the local-only picker runs at the right time on a fresh enroll, but it still silently skips there (prints only the durable hint). Diagnosed on a real fresh box (full ~/.hyp wipe + v1.13.0 enroll to prod).
Root cause chain:
hyp remote loginboots its kernel at dispatch time, before enrollment. On a fresh box the local config names no plugins;@hypaware/ai-gateway(which registers theai_gateway_messagesdataset) only arrives via the org config-control pull the daemon does afterenrollCentralSinkinstalls it. The login process'sctx.queryboot snapshot never learns about it.listCapturedDirectorieshits "SQL query references unknown dataset" -> best-effortnull.waitForCapturedDirectoriesreadsnullas "enumeration cannot run, stop immediately" (no 30s poll).enumeration_failed-> durable hint only.The #283 tests stubbed
waitForCaptured/listCandidates, so this was never exercised; a re-login on a populated box works (plugins load from the applied central layer at CLI boot), which is why manual verification passed.Fix
freshenCaptureEnumeration(src/core/cli/remote_commands.js): on the fresh-enroll interactive fork, afterwaitForClientAttachreturns a client, re-boot one fresh kernel (config profile, the same layered resolution any subsequenthypcommand runs) and hand its registry's enumeration to the capture wait.sources.stopAll, mirroring dispatch's boot-source cleanup) after the picker, so the login process still exits.local_only.jsexportsCAPTURE_DATASETso the registry check and the enumeration SQL cannot drift. LLP 0069/0080 carry forward-ref notes per the immutable-record convention.Tests
nullrefresh falls back to the snapshot and the login still succeeds.freshenCaptureEnumerationsnapshot no-op (no boot paid), success, dataset-still-missing (sources stopped, null), boot-throw (null).bootKernelagainst an on-disk central layer naming@hypaware/ai-gatewayand asserts enumeration RUNS (empty list, pollable) instead of failing to null.npm test: 2129 pass.npm run build:types: clean.core_boot_noopsmoke: ok. (walkthrough_picker_to_first_queryfails identically on clean origin/master - pre-existing, unrelated.)Note: filing a follow-up GitHub issue for this residual was blocked in this autonomous session; linkage is preserved here and in the LLP forward-notes as "issue #281 follow-up".
🤖 Generated with Claude Code