Files
2026-08-24 11:09:03 +00:00

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, and end notifications 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.ts
  • apps/web/lib/lsp/lsp-progress.test.ts
  • apps/web/lib/lsp/lsp-client-types.ts
  • apps/web/lib/lsp/lsp-json-rpc.ts
  • apps/web/lib/lsp/lsp-client-manager.ts
  • apps/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.workDoneProgress and 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/didSave after successful persistence. Unchanged buffers retain canonical repo-aware includeText snapshots; 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 textEdit use Monaco's current-word range while InsertReplaceEdit keeps 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 through 4007 before 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 explicit GOBIN, GOPATH, or HOME.
  • 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 4001 now 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 false for unresolved targets, while agentctl reports unexpected server exit as categorical 4006 with no English close reason so the browser localizes it.
  • Review hardening: JSON-RPC initialize errors now preserve their message instead of rendering [object Object], while task-host process-launch failures retain details in backend logs and close through localized categorical 4008 with no English transport reason.
  • Review hardening: task teardown during auto-install keeps the standard 1001 going-away close but omits the English task stopping reason, 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 isIncomplete state reaches Monaco so continued typing can request refreshed results through trigger kind 3 instead 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 installing WebSocket 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 relative GOPATH entry, HOME, and USERPROFILE, preventing repository-controlled directories from supplying the launched gopls binary 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.ts
    • pnpm exec vitest run lib/lsp/lsp-providers.test.ts --reporter=dot
    • 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 (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 bare 4003 fallback)
    • 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 typecheck
    • pnpm exec eslint lib/lsp/lsp-providers.ts lib/lsp/lsp-providers.test.ts e2e/tests/lsp/lsp-file-intelligence.spec.ts
    • go test ./internal/agentctl/server/api ./internal/lsp/installer ./internal/tools/installer
    • go test ./internal/tools/installer ./internal/lsp/installer (Windows USERPROFILE result discovery included)
    • GOOS=windows GOARCH=amd64 go test -c ./internal/tools/installer
    • go test ./internal/agent/runtime/lifecycle ./internal/gateway/websocket
    • go test -race ./internal/gateway/websocket -run 'Test(HandleLSPConnectionChecksCapacityBeforeEnsuringExecution|ResolveLSPExecution)' (capacity ordering and release)
    • make lint
    • GOOS=windows GOARCH=amd64 go test -c ./internal/lsp/installer and ./internal/agentctl/server/api
    • pnpm 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, and pnpm i18n:ratchet
    • pnpm 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.ts
    • pnpm 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=1
    • go test ./internal/agentctl/server/api -run 'Test(HandleLSPStreamAutoInstallHandsFirstClientMessageToBridge|LSPAutoInstallIsCanceledByClientDisconnect|LSPAutoInstallIsCanceledAndDrainedByInstanceTeardown)' -count=1
    • go test -race ./internal/agentctl/server/api -run 'Test(HandleLSPStreamAutoInstallHandsFirstClientMessageToBridge|LSPAutoInstallIsCanceledByClientDisconnect)' -count=1
    • go test ./internal/tools/installer -run 'Test(FindGoBinaryWithRunnerRejectsRelativeDirectories|FindGoBinaryWithRunnerUsesUserProfileFallback|GoInstallStrategyUsesRunnerEnvironmentForLookupAndResult)' -count=1
    • go test ./internal/tools/installer -count=1
    • node --test scripts/validate-public-docs.test.mjs scripts/notify-docs-workflow.test.mjs && node scripts/validate-public-docs.mjs