14 KiB
14 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec |
|---|---|---|---|---|---|---|
| 01-progress-protocol | Work-done progress protocol | completed | 1 | plan.md | ../../specs/platform/requirements/lsp-file-intelligence.md |
Task 01: Work-Done Progress Protocol
Acceptance
- The initialize request advertises work-done support and carries a connection-generation token before any server progress can arrive.
- Valid
begin,report, andendnotifications update only their registered string or number token; malformed, unknown, and stale-generation frames do nothing. - Initialization, active work, and the most recently completed server item are observable through one stable manager snapshot and clear with connection ownership.
Verification
cd apps && pnpm --filter @kandev/web test -- --run lib/lsp/lsp-progress.test.ts lib/lsp/lsp-client-manager.test.ts
cd apps/web && pnpm run typecheck
Files Likely Touched
apps/web/lib/lsp/lsp-progress.tsapps/web/lib/lsp/lsp-progress.test.tsapps/web/lib/lsp/lsp-client-types.tsapps/web/lib/lsp/lsp-json-rpc.tsapps/web/lib/lsp/lsp-client-manager.tsapps/web/lib/lsp/lsp-client-manager.test.ts
Dependencies
None.
Parallelism
Sequential; Task 02 consumes this snapshot.
Inputs
- Spec sections: Browser LSP progress contract, Readiness and progress state, Failure modes.
- Existing generation checks in
lsp-client-manager.ts.
Output Contract
Record RED/GREEN evidence, files changed, exact tests run, remaining risks, and update this task plus plan.md.
Result
- RED: the manager test proved
window.workDoneProgressand the initialize token were absent; transition tests then proved begin/report/end state was unimplemented. - GREEN: the client now advertises and registers generation-owned tokens, tracks initialize timing and immutable work snapshots, and ignores malformed, unknown, or stale progress.
- Review hardening: unexpected closes after readiness now retain an error status and close reason for Retry; explicit stop and idle cleanup still clear to disabled.
- Review hardening: a dedicated synchronous registration guard now distinguishes LSP TypeScript providers from Monaco's lazy built-ins, and built-in suppression waits until Monaco's wrappers are installed.
- Review hardening: a generic WebSocket close no longer overwrites a detailed install failure already reported by agentctl.
- Review hardening: completion providers forward Monaco trigger context using LSP enum values, and managed installer caches resolve from the merged task
HOME. - Review hardening: cold SSH, Sprites, and remote-Docker sessions are rejected through a read-only runtime lookup before LSP can create or resume an execution.
- Review hardening: both Monaco save paths now flush the newest live content before emitting capability-gated
textDocument/didSaveafter successful persistence. Unchanged buffers retain canonical repo-awareincludeTextsnapshots; buffers edited during persistence remain dirty and omit stale optional save text instead of rewinding LSP state. - Review hardening: LSP navigation into an attached repository preserves an existing task-root-relative editor identity, preventing duplicate tabs and keeping cursor reveal on the tree-opened file.
- Review hardening: command-palette content-search selection now carries the active session through pending and immediate cursor reveal, so identical open repository paths in other task sessions cannot make the jump ambiguous.
- Review hardening: installer failures without details, WebSocket errors, and reasonless pre-bridge or post-bridge closes now resolve their fallback copy through the active locale instead of leaking English into localized status UI and toasts.
- Review hardening: categorical task-host close codes for unsupported executors, capacity, and stream failures ignore English transport prose and resolve their status through the active frontend locale.
- Review hardening: completion items without
textEdituse Monaco's current-word range whileInsertReplaceEditkeeps its dual range, live LSP JSON settings update the reused connection and its configuration request handler, and task hosts without an installer close with localized manual-install guidance through4007before or after preference opt-in. - Review hardening: TypeScript built-in suppression now follows per-connection model ownership instead of a global flag, so unrelated sessions keep Monaco intelligence; valid empty semantic-token arrays return an empty payload without periodic client polling.
- Review hardening: Go post-install discovery now includes the task environment's
USERPROFILE\go\bin, covering default Windows Local PC setups without explicitGOBIN,GOPATH, orHOME. - Review hardening: the browser-facing LSP capacity slot is acquired before
GetOrEnsureExecution, so an over-cap request cannot start or resume a supported task host; all resolution failures release the provisional slot. - Review hardening: missing-binary close code
4001now ignores backend prose and resolves through the active locale, Editors cards expose install prerequisites inline for pointer, keyboard, and touch users, and the test-only duplicate language table was removed in favor of the localized Settings metadata source. - Review hardening: the Monaco editor opener now opens regular targets inside the active task workspace and propagates
falsefor unresolved targets, while agentctl reports unexpected server exit as categorical4006with no English close reason so the browser localizes it. - Review hardening: JSON-RPC initialize errors now preserve their
messageinstead of rendering[object Object], while task-host process-launch failures retain details in backend logs and close through localized categorical4008with no English transport reason. - Review hardening: task teardown during auto-install keeps the standard
1001going-away close but omits the Englishtask stoppingreason, allowing the browser's existing localized pre-bridge fallback to own the user-visible status. - Review hardening: Monaco completion registration now uses only the trigger characters advertised by the active server, and a named 25-value mapping preserves every standard LSP completion category in Monaco instead of relying on mismatched numeric enums.
- Review hardening: Monaco signature help is absent when the server omits that capability and otherwise preserves the server's trigger and retrigger characters; a bare install-failure close ignores generic task-host prose and resolves through the active locale while a preceding detailed installer payload remains authoritative.
- Review hardening: LSP completion-list
isIncompletestate reaches Monaco so continued typing can request refreshed results through trigger kind3instead of retaining stale partial suggestions. - Review hardening: completion, hover, definition, references, and signature help register only when advertised; TypeScript built-in suppression now follows the exact overlapping provider set, preserving built-in fallbacks for omitted capabilities and unwired rename, code-action, highlight, and inlay features.
- Review hardening: every task-host LSP WebSocket frame now uses the same five-second write deadline, so an unread pre-bridge status or ready frame cannot pin the handler or leak its owned language-server process.
- Review hardening: a terminating stdout forwarder closes language-server stdin to release active writes immediately, while a cross-platform 30-second cutoff closes a pipe whose server remains alive but stops reading; both paths converge on owned-process cleanup.
- Review hardening: a single pending task-host WebSocket read cancels connection-owned auto-install work when the browser stops or disconnects, then hands the first client frame into the bridge after a successful install without concurrent reads or a dropped initialize request.
- Review hardening: a failed or timed-out initial
installingWebSocket write now closes the stream before agentctl acquires auto-install work; the forced-write-failure regression proves the installer is never entered without a consumer. - Review hardening: Go post-install lookup now rejects relative
GOBIN, every relativeGOPATHentry,HOME, andUSERPROFILE, preventing repository-controlled directories from supplying the launchedgoplsbinary while retaining absolute task-host fallbacks. - Verified:
pnpm --filter @kandev/web test -- --run lib/lsp/lsp-progress.test.ts lib/lsp/lsp-client-manager.test.tspnpm exec vitest run lib/lsp/lsp-providers.test.ts --reporter=dotpnpm exec vitest run lib/lsp/lsp-providers.test.ts lib/lsp/lsp-client-manager.test.ts lib/lsp/lsp-client-manager.progress.test.ts(45 passed, including advertised completion triggers and all 25 standard completion kinds)pnpm exec vitest run lib/lsp/lsp-providers.test.ts lib/lsp/lsp-language-mapping.test.ts lib/lsp/lsp-client-manager.progress.test.ts(33 passed, including signature-help capability gating/triggers and localized bare4003fallback)pnpm exec vitest run lib/lsp/lsp-providers.test.ts lib/lsp/lsp-client-manager.test.ts lib/lsp/lsp-client-manager.progress.test.ts lib/lsp/lsp-language-mapping.test.ts(55 passed, including incomplete completion-list preservation)pnpm exec vitest run lib/lsp/lsp-providers.test.ts components/editors/monaco/builtin-providers.test.ts lib/lsp/lsp-client-manager.test.ts lib/lsp/lsp-client-manager.progress.test.ts lib/lsp/lsp-client-manager.document-sync.test.ts lib/lsp/lsp-language-mapping.test.ts(63 passed, including optional-provider gating and feature-scoped TypeScript fallback)pnpm exec vitest run lib/lsp/lsp-providers.test.ts components/editors/monaco/builtin-providers.test.ts lib/lsp/lsp-client-manager.test.ts lib/lsp/lsp-client-manager.progress.test.ts lib/lsp/lsp-client-manager.document-sync.test.ts(49 passed)pnpm run typecheckpnpm exec eslint lib/lsp/lsp-providers.ts lib/lsp/lsp-providers.test.ts e2e/tests/lsp/lsp-file-intelligence.spec.tsgo test ./internal/agentctl/server/api ./internal/lsp/installer ./internal/tools/installergo test ./internal/tools/installer ./internal/lsp/installer(Windows USERPROFILE result discovery included)GOOS=windows GOARCH=amd64 go test -c ./internal/tools/installergo test ./internal/agent/runtime/lifecycle ./internal/gateway/websocketgo test -race ./internal/gateway/websocket -run 'Test(HandleLSPConnectionChecksCapacityBeforeEnsuringExecution|ResolveLSPExecution)'(capacity ordering and release)make lintGOOS=windows GOARCH=amd64 go test -c ./internal/lsp/installerand./internal/agentctl/server/apipnpm e2e:run -- --project=chromium tests/lsp/lsp-file-intelligence.spec.ts(13 passed)pnpm e2e:run tests/lsp/lsp-file-intelligence.spec.ts -- --grep "runs Kotlin intelligence through the task host"(1 production-build Chromium scenario passed)pnpm exec vitest run lib/lsp/lsp-document-sync.test.ts lib/lsp/lsp-client-manager.test.ts lib/lsp/lsp-client-manager.document-sync.test.ts hooks/use-file-save-delete.test.ts components/task/task-center-panel-restoration.test.ts(46 passed)pnpm exec vitest run hooks/use-file-save-delete.test.ts hooks/use-lsp-file-opener.test.ts lib/lsp/lsp-client-manager.document-sync.test.ts components/task/task-center-panel-restoration.test.ts lib/lsp/lsp-document-sync.test.ts(35 passed)pnpm test(1,122 files; 8,657 passed, 4 skipped)pnpm lint,pnpm run typecheck,pnpm i18n:check, andpnpm i18n:ratchetpnpm exec vitest run lib/lsp/lsp-language-mapping.test.ts components/settings/lsp-language-cards.test.tsx components/settings/lsp-language-options.test.ts(13 passed)pnpm exec eslint lib/lsp/lsp-json-rpc.ts lib/lsp/lsp-language-mapping.test.ts components/settings/lsp-language-cards.tsx components/settings/lsp-language-cards.test.tsx components/settings/lsp-language-options.ts components/settings/lsp-language-options.test.tspnpm exec vitest run hooks/use-lsp-file-opener.test.ts components/editors/monaco/monaco-init.test.ts lib/lsp/lsp-language-mapping.test.ts components/settings/lsp-language-cards.test.tsx components/settings/lsp-language-options.test.ts(23 passed)go test ./internal/agentctl/server/api -count=1(categorical server-exit close included)pnpm exec vitest run lib/lsp/lsp-client-manager.test.ts lib/lsp/lsp-client-manager.progress.test.ts lib/lsp/lsp-language-mapping.test.ts hooks/use-lsp-file-opener.test.ts components/editors/monaco/monaco-init.test.ts components/settings/lsp-language-cards.test.tsx components/settings/lsp-language-options.test.ts(56 passed)go test ./internal/agentctl/server/api -count=1(categorical process-start failure included)go test ./internal/agentctl/server/api -run 'TestHandleLSPStream(BridgesFramesAndStopsOwnedProcess|StopsProcessWhenForwardingToWebSocketFails|PeerCloseReleasesBlockedForwarderWrite)' -count=1(ready-frame deadline and bridge cleanup)go test ./internal/agentctl/server/api -count=1(bounded task-host status and ready writes included)go test ./internal/agentctl/server/api -run 'Test(RunLSPBridgeForwarderExitUnblocksStdinWrite|WriteLSPStdinWithTimeoutClosesBlockedWrite)' -count=1(forwarder cleanup and virtual-time stdin cutoff)go test -race ./internal/agentctl/server/api -run 'Test(RunLSPBridgeForwarderExitUnblocksStdinWrite|WriteLSPStdinWithTimeoutClosesBlockedWrite)' -count=1go test ./internal/agentctl/server/api -run 'Test(HandleLSPStreamAutoInstallHandsFirstClientMessageToBridge|LSPAutoInstallIsCanceledByClientDisconnect|LSPAutoInstallIsCanceledAndDrainedByInstanceTeardown)' -count=1go test -race ./internal/agentctl/server/api -run 'Test(HandleLSPStreamAutoInstallHandsFirstClientMessageToBridge|LSPAutoInstallIsCanceledByClientDisconnect)' -count=1go test ./internal/tools/installer -run 'Test(FindGoBinaryWithRunnerRejectsRelativeDirectories|FindGoBinaryWithRunnerUsesUserProfileFallback|GoInstallStrategyUsesRunnerEnvironmentForLookupAndResult)' -count=1go test ./internal/tools/installer -count=1node --test scripts/validate-public-docs.test.mjs scripts/notify-docs-workflow.test.mjs && node scripts/validate-public-docs.mjs