Uh oh!
There was an error while loading. Please reload this page.
Add first-party OpenCode CLI and Desktop capture - #998
Conversation
… docs Review round 1 on PR #997 at d20d807. - `exportBatch` resolved the wire target OUTSIDE the per-partition try. `forwardingTarget` now throws (unresolvable dataset), and that throw escaped `exportBatch` into the driver's outer catch, which respools the whole batch and reports zero exported, discarding partitions already POSTed in the same loop. Resolve inside the try so one bad partition costs one partition, which is the contract the loop documents. - The registration path escaped the dataset name and the ingest path did not, so with an arbitrary dataset name in `/v1/ingest/{signal}` the two calls could name different resources (and `joinUrl`'s `new URL()` would normalize a `..` segment out). Escape both the same way; the four legacy signals are encode-invariant, so their URLs are unchanged. - `TELEMETRY_EVENTS_SOURCE_SIGNAL`'s docstring still said rows POST to `/v1/ingest/claude_telemetry` and that the declaration exists so forwarding "never falls back to the dataset name", which is now exactly what happens. Corrected; its LLP 0255 ref still holds. - `proto.md` documented no `PUT /v1/datasets/{name}` and still said `{signal}` is one of four. Document the announce call and the two ways a signal now resolves, and mark the server side unverified from this repo. - `isCurrent`'s JSDoc said two things can go stale; there are three now. Document the mode axis, and give `ActionMarker.mode` a typed field beside its `endpoint` / `assets_key` siblings instead of leaving it `unknown` under the index signature. - Tests pinning the claimed bounds rather than restating them: the announce happens once per sink instance across two ticks; a rejected announce fails the partition, never reaches ingest, and is NOT remembered (so the next tick re-announces); an unresolvable dataset fails only its own partition. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
eaf363b to
3a16446Compare…eam (#998 review) Verified against a real OpenCode 1.18.22 server, not a fixture we wrote. The installed plugin called `client.session.get({ sessionID: id })`. The generated OpenCode SDK client takes route parameters under `path`, so `/session/{id}` went out unsubstituted and the server answered 500. Every snapshot carried an error envelope, which the listener could only report as a missing cwd. The live lane recorded nothing at all and said so in a counter that meant something else. Reproduced and fixed, then re-verified end to end: a real `session.created` now delivers the session and its messages to the listener. Second defect, reproduced against the listener: OpenCode messages mutate under a stable id, while the shared projected-exchange writer dedupes at message grain. The first snapshot of an in-flight turn froze its streaming prefix, and neither a later snapshot nor the export lane could replace it (the recovery seed reads the same committed message ids). A turn observed mid-stream was permanently truncated with its tool result missing. The projector now waits for a settled assistant message, which is the message-grain form of the part-grain rule already there, and for the same reason: whatever lands first wins forever. Also: - `message.part.updated` carries the part alone, so the highest-frequency wake-up in the stream resolved to no session id and was dropped. - Two smoke flows counted bundled plugins and picker rows by hand and were not updated for the new adapter; both failed on this branch and pass now. - The exact-id recovery path dropped a `.hypignore` session with no event, so the withhold was invisible in the run report. - `attach --dry-run` claimed it installed a file and asked for a restart. - CLAUDE.md gained the acceptance procedure entry and the smoke battery line; the acceptance doc's second import window was degenerate and would have passed without testing the dedupe it exists to test. Regression tests cover both headline defects and fail without the fixes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
philcunliffe
commented
Aug 24, 2026
Review round 1 - findings, fixed and pushedReviewed head I did not review this against fixtures alone. The two headline findings were confirmed by running the adapter against a real OpenCode 1.18.22 ( Findings1. CRITICAL - the live lane captured nothing. The installed plugin called Both reads 500, and Fixed, and re-verified end to end against a real Also: a failed SDK read now drops the snapshot instead of shipping the error envelope, so 2. HIGH - a turn observed mid-stream was permanently truncated. OpenCode messages mutate under a stable id: text streams in and tool parts settle after the message id already exists. The shared writer dedupes at message grain ( The complete text and the completed Fixed by waiting for a settled assistant message ( 3. HIGH - two smoke flows failed on this branch. Both count bundled plugins / picker rows by hand and were not updated for the new adapter. 4. MEDIUM -
5. MEDIUM - open, not fixed: endpoint drift on the endpoint-free attach path.
6. LOW - exact-id recovery dropped a 7. LOW - Checked and found clean: One finding I disproved. The review pass flagged the backfill reading [{ "id": "ses_...", "title": "probe", "updated": 1787615096538,
"created": 1787615096538, "projectId": "global", "directory": "..." }]I also confirmed (a) Stacked baseThe diff is coherent against (b) Privacy and column classificationClean, and it is the failure mode you asked about that makes it clean. The adapter registers no dataset of its own: it reuses One note, not a blocker: (c) Acceptance procedurePresent - (d) LLP coverageLLP 0306 is present, Tests
VerdictGood design, a genuinely well-written acceptance procedure, and a solid privacy posture. But at |
# Conflicts: # hypaware-core/plugins-workspace/central/proto.md # hypaware-core/plugins-workspace/central/src/sink.js # llp/0014-sinks.spec.md # llp/0305-open-dataset-central-forwarding.decision.md # src/core/config/action_attach.js # test/plugins/central-forward-chunking.test.js
…#998) Five review findings on the OpenCode CLI/Desktop capture PR. F1 `hyp setup`'s attach lane and `hyp status`'s clients line resolved clients through the AI gateway capability, whose getClient/listClients filter to registrations with a gateway upstream. An endpoint-free client (LLP 0306) is therefore invisible to both: a solo pick skipped the attach block entirely, a mixed pick recorded the adapterless not-applicable result meant for Claude Desktop (LLP 0115) while attaching nothing, and status omitted the client. Both now read the intrinsic registry, which is the superset, and hand no endpoint to an adapter that declares it needs none. The CA wait is skipped when no gateway is active, since there is no proxy CA to wait for. F2 One unreadable session aborted the whole backfill run: the per-session `opencode export` and its JSON.parse were unguarded inside the loop, so a single throw dropped every remaining session (up to 1000). Warn and continue, matching codex and openclaw. F3 The listener's stop() called only server.close(), which waits on outstanding sockets, so a connected OpenCode blocked `hyp daemon stop`. Close idle and then all connections, like every peer listener. F4 The unowned-plugin-file collision threw a plain Error, which the reconciler classified as a retryable failure and re-attempted forever on a condition only the user can clear. Mark it refused (LLP 0186). F5 An errored assistant turn set a message-grain raw_frame that row expansion can never reach, because every projected block carries its own part frame and the block's wins. The error rides message attributes instead, where it lands on a row. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
philcunliffe
commented
Aug 25, 2026
Review round 2 of 2 — head |
philcunliffe
commented
Aug 25, 2026
Triage at head |
philcunliffe
commented
Aug 25, 2026
Ship risk: |
Uh oh!
There was an error while loading. Please reload this page.
Two conflicting hunks in src/core/config/action_attach.js, both in isCurrent(). #998 made the endpoint freshness key conditional on the client's requiresEndpoint flag (LLP 0306); this branch added a fourth, adapter-owned freshness key (LLP 0308). Both hold: the endpoint check keeps master's requiresEndpoint guard, and the adapter key is still read before attach() in perform() and still checked last in isCurrent(), after the three pure keys. readAttachKey() in isCurrent() now reuses the `registration` binding master introduced instead of resolving getClient(client) a second time. attachKey?() landed on master's new ClientRegistration base, which AiGatewayClientRegistration extends, so codex keeps the hook and the new opencode client correctly declares none. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Conflict: the AGENTS.md release-checklist smoke battery. master (#998) added `opencode_capture` to the list; this branch rolled every entry to the canonical `hyp dev smoke` spelling. Kept both: master's full list, `opencode_capture` in its position included, on the `hyp dev smoke` spelling. No `hyp smoke ` occurrence remains in the file. hypaware-plugin-kernel-types.d.ts merged cleanly. This branch's addition there is a `CommandRegistry.register` docstring only, so nothing in the contract's shape moved.
Summary
Testing
npm test(5,231 passed, 2 skipped)npm run typechecknpm run smoke -- opencode_capturenpm pack --dry-runnode scripts/llp-numbers.js checkgit diff --checkNotes