Co-authored-by: Kandev Agent <agent@kandev.dev>
5.6 KiB
id, title, status, wave, depends_on, plan, requirements, acceptance_criteria, system_design
| id | title | status | wave | depends_on | plan | requirements | acceptance_criteria | system_design | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-normalize-tool-file-paths | Normalize tool file paths | done | 1 | plan.md |
|
|
|
Task 01: Normalize Tool File Paths
Summary
Give tool-originated workspace files one relative identity before editor, pending-cursor, and scroll state is written, while leaving external absolute content reads unchanged.
In scope
- Add the shared frontend workspace-path classifier and normalizer.
- Handle POSIX and Windows roots, separator normalization, drive, UNC, and Windows file URI casing, and complete-segment containment.
- Normalize read and edit tool opens inside
useOpenFileAtLinebefore every editor and cursor call. - Use the same containment decision for the edit-card open affordance instead of raw string prefix matching.
- Reuse the helper in the LSP opener where it replaces equivalent local path logic without changing LSP behavior.
- Add desktop and phone end-to-end coverage for an agent read card containing the active workspace's absolute file path and a line target.
Out of scope
- File-tree expansion, restore, refresh, or backend validation from Task 02.
- Blocking an external absolute path from the read-only content endpoint.
- New editor or phone-viewer UI.
Acceptance
- A contained absolute tool path opens, keys its pending cursor, and scrolls as the corresponding workspace-relative path.
- A path outside the workspace or sharing only its string prefix remains absolute and does not gain workspace identity.
- Desktop and phone open the same relative workspace file at the requested line through their existing editor/viewer surfaces.
TDD start
First add a useOpenFileAtLine regression that passes /workspace/src/app.ts with workspace root
/workspace and expects src/app.ts in setPendingCursorPosition, onOpenFile, and
scrollEditorIfMounted. It fails today because all three receive the absolute path. Add the prefix
collision and external absolute cases before changing production code.
ASCII UI preview
Relevant excerpt from UI-01:
Desktop: Read /workspace/public/.../case.json -> Editor public/.../case.json
Phone: Read /workspace/public/.../case.json -> native viewer public/.../case.json
External /opt/reference.md -> existing read-only viewer; Files unchanged
The rendered components and navigation remain unchanged. Only the path identity crossing the existing open action changes.
Verification
Run from the repository root:
(cd apps && pnpm install --frozen-lockfile)
(cd apps/web && pnpm exec vitest run lib/workspace-file-path.test.ts \
hooks/use-file-editors.test.tsx components/task/chat/messages/tool-edit-message.test.tsx \
hooks/use-lsp-file-opener.test.ts)
(cd apps/web && pnpm run typecheck)
(cd apps/web && pnpm exec eslint lib/workspace-file-path.ts hooks/use-file-editors.ts \
components/task/chat/messages/tool-edit-message.tsx hooks/use-lsp-file-opener.ts \
--max-warnings 0)
(cd apps/web && pnpm e2e:run --project chromium \
tests/task/chat-read-absolute-workspace-path.spec.ts)
(cd apps/web && pnpm e2e:run --project mobile-chrome \
tests/task/mobile-file-viewer.spec.ts --grep "absolute workspace read link")
Files likely touched
apps/web/lib/workspace-file-path.tsapps/web/lib/workspace-file-path.test.tsapps/web/hooks/use-file-editors.tsapps/web/hooks/use-file-editors.test.tsxapps/web/hooks/use-lsp-file-opener.tsapps/web/hooks/use-lsp-file-opener.test.tsapps/web/components/task/chat/messages/tool-edit-message.tsxapps/web/components/task/chat/messages/tool-edit-message.test.tsxapps/web/e2e/tests/task/chat-read-absolute-workspace-path.spec.tsapps/web/e2e/tests/task/mobile-file-viewer.spec.ts
Dependencies
None.
Risks
- The pending cursor map must use the normalized identity before the editor mounts.
- Tool edit cards currently use a permissive prefix test; changing it must preserve their existing copy-path fallback for external files.
file:///roots used by Monaco tests need canonical handling without treating an arbitrary URI as a tree path.
Parallelism
sequential
Inputs
AC-UI-FILE-TREE-PATH-SCOPE-001.1,.2, and.6.- Path identity and tool-file open flow in the system design.
- ADR 0016's external absolute content-read exception.
Results
Implemented the shared path classifier and normalized workspace-contained read and edit paths before editor, pending-cursor, and scroll state is written. The edit-card containment check and LSP alias conversion now use the same segment-aware helper. External absolute paths remain unchanged.
PR review extended the Windows comparison rule to UNC paths, drive file URIs, and hosted file URIs, matching the existing LSP identity semantics. The duplicated desktop and phone workspace polling helper now lives in the shared E2E session helper.
Validation passed:
- Four focused unit files passed with 56 tests.
- Frontend typecheck and changed-file ESLint passed.
- The Chromium desktop regression passed with one test and observed only relative tree requests.
- The Pixel 5 phone regression passed with one test and reached the requested line in the existing native viewer.
- Post-review verification passed the six-file focused frontend suite with 78 tests, frontend typecheck and changed-file ESLint, and both focused Playwright scenarios.