feat(kernel): register the real PhotoCameraAdapter as adapterType "photo" (G-8b, fail-loud, no mock fallback) - #332
Draft
LamaSu wants to merge 3 commits into
Draft
Conversation
…rType "photo" PhotoCameraAdapter was exported but constructed nowhere: a kernel config could not name the real photo-evidence camera, so operators had only "mock". Adds "photo" to the AdapterType union and a buildPhotoCamera factory registered alongside the other camera built-ins. - Storage-less PhotoCaptureService (hash-derived `photo:sha256:...` ref), the same choice routes/photo-verification.ts makes. createEvidenceStorage() is async while CameraAdapterFactory is sync, and the service's byte-upload path would label a hash-derived id `storacha://` — misstated provenance. - Gemini is opt-in only: `config.gemini: true` (key from config.geminiApiKey or GEMINI_API_KEY) or an injected service. A keyless service silently degrades to local pHash+SSIM while the adapter still stamps model "gemini-2.0-flash" on the emitted evidence, so a missing key throws rather than downgrades. - Misconfiguration throws a clear error naming the device; no mock fallback. globalMockMode=true still yields MockCameraAdapter (existing contract). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…l-loud capture 12 tests in photo-camera-registration.test.ts: - "photo" is registered; createCameraAdapter returns a real PhotoCameraAdapter (not MockCameraAdapter), with source.deviceType "camera" and the device id. - NEGATIVE CONTROL: factory-built adapter with no bytes pushed rejects captureSnapshot() with /No image bytes available/ and emits ZERO events, so nothing fabricated can enter a signed bundle. A consumed capture is not reused. - Push-fed happy path: setNextCapture(bytes) -> captureSnapshot() returns an imageHash equal to node:crypto SHA-256 of those exact bytes, plus a hash-derived storageRef; distinct bytes yield distinct hashes. - createAdaptersFromConfig: mockMode:false -> one PhotoCameraAdapter; mockMode:true -> MockCameraAdapter (global-mock contract preserved). - Gemini: an injected service is actually used by runInspection; gemini:true with no key throws; a malformed gemini/geminiApiKey throws, never mocks. Also extends the built-ins assertion in adapter-factory.test.ts and the supported-adapterType list in kernel-config.test.ts with "photo". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gistration Outcome, design note, files changed with line ranges, raw test + typecheck tails, the quoted negative-control assertion, and honest gaps: no job-path setNextCapture caller yet (hook site named at job-runner.ts:121-127), no job-nonce binding (CP-0 (c)), no pcc-node equivalent, and the untouched packages/spec adapterType/manifest divergence. ai/ is gitignored; force-added so the report travels with the branch bundle, matching ai/lane-runs/jobrunner-safety/REPORT.md in history. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes memo sub-blocker G-8b (PhotoCameraAdapter exported but not registered by the standard factory). Ledger items: G-8 / MS-11 / LO-SE-1 precondition. Bounded implementer run on the DGX Spark (
photo-camera-reg-implementer-1), branch offlamasu/master7a86491.What changes (packages/kernel only, +601/-1, no new deps)
AdapterTypegains"photo";registerCameraAdapter("photo", buildPhotoCamera)next to the other built-ins.buildPhotoCameraconstructs the realPhotoCameraAdapterwith a hash-onlyPhotoCaptureService(theroutes/photo-verification.ts:18precedent; the factory is sync and cannot receive the async evidence storage). Gemini is opt-in only (cfg.gemini: true+ key, or an injectedcompare()service);gemini:truewith no key throws rather than silently degrading while stampinggemini-2.0-flashprovenance.unknownAdapterTypeErrorcontract).mockMode:truestill yields the mock camera.Negative control (memo: a missing photo must fail loud, never fabricate)
packages/kernel/src/__tests__/photo-camera-registration.test.ts:102-112: the factory-built adapter with no bytes pushed rejectscaptureSnapshot()withNo image bytes availableand emits zero evidence events.Verification
pnpm --filter @pcc/kernel test38 files / 875 passed;tsc --noEmitclean. 12 new tests.photo-camera-registration + adapter-factory + adapter-honesty= 87/87 passed (519 ms).Honest gaps (report in
ai/lane-runs/photo-camera-reg/REPORT.md)setNextCapture()yet, so a tier-2 job with aphotocamera fails closed at the before-snapshot (correct, but not usable end-to-end). Hook candidates:job-runner.ts:121-127(load-bearing),routes/photo-verification.ts:75-92(POST /api/photo/uploadalready has the bytes).adapterType: "camera"(unregistered) and has no upload path.packages/spechas a divergentAdapterTypeunion and nophotoentry inADAPTER_DEFAULT_MANIFESTS(one-line data additions, left for composition/spec owners).Reviewers: sensors 7a438686, gateway 0600b204. Steward 57c2a412 graded. Operator merges (no lane merges to master).
🤖 Generated with Claude Code
https://claude.ai/code/session_012PxrWRej6UAvZepXkpxJPi