Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# AGENTS.md

Instructions for coding agents working in this repository.

## Read this first

Before changing any code:

1. **[docs/MEMORY.md](docs/MEMORY.md)** — constraints that are expensive to rediscover.
Entry #1 alone will cost you an hour if you touch `Package.swift` without it.
2. **[docs/CURRENT_STATE.md](docs/CURRENT_STATE.md)** — what works, what does not, what is
next. Do not re-implement something that already works.
3. **[docs/IDEA.md](docs/IDEA.md)** — what this project is for, and what it deliberately is not.

---

## Keeping the documentation true is part of the work

**The `.md` files in `docs/` describe the current state of the code. If your change makes any
of them wrong, fixing that file is not optional cleanup — it is part of the change.**

This matters more here than in most projects, because `docs/MEMORY.md` is the only record of
several constraints that cost real time to discover. A stale entry does not just misinform a
reader; it sends the next person — or the next agent — into the same dead end, and they have
no way to tell the file is stale.

### When to update which file

| Your change | Update |
|---|---|
| Anything in `Sources/` or `Tests/` that changes what works | **CURRENT_STATE.md** — features, tests table, sizes |
| Worked around a dependency, a toolchain limit, an SDK quirk | **MEMORY.md** — new numbered entry, or amend the relevant one |
| Found a trap you fell into | **MEMORY.md** — what happened, what it cost, what to do |
| Added, removed or upgraded a dependency | **STACK.md** — versions table and the rationale below it |
| Added or removed a module, or changed a data flow | **ARCHITECTURE.md** |
| Changed how work is expected to happen | **PROCESS.md**, **BRANCHING.md**, **COMMITTING.md** |
| Changed what the project is for | **IDEA.md** |
| Changed the public surface, CI, or setup | **README.md** |

### The rule

If you had to read something to understand your change, it belonged in a `.md` file and
probably does not exist yet. Write it.

If you found something that contradicts a `.md` file, fix the file in the same commit. A
stale document is a defect, not a matter of taste — and it is worse than a missing one,
because a missing file announces ignorance while a wrong file is trusted.

### When the current state is knowingly wrong

Do not paper over it. Write it down as a limitation with an issue number, the way
`TerminalSession`'s pipes-not-a-PTY is handled:

```
## Not working

**The terminal has no PTY.** Pipes, so no job control and no TTY.
[#5](https://github.com/Yan123-tech/code-editor/issues/5)
```

An honest gap is useful. A hidden gap is a trap for whoever inherits this.

---

## Local gate — CI does not build

**Run all three before every push. CI checks formatting and syntax only.**

```bash
swift build && swift test
swift-format lint --recursive --strict --configuration .swift-format Sources Tests
```

Reason: no hosted runner has SwiftPM 6.4, which `CodeEditSourceEditor` 0.15 needs to
generate its resource bundles. Full details and the failed attempts in
[docs/MEMORY.md](docs/MEMORY.md#1-ci-cannot-build-this-package-do-not-try-to-make-it).

Never imply in a commit message or PR that CI verified the build. It did not.

---

## Conventions

- **Conventional Commits**, scopes are modules: `core`, `themes`, `terminal`, `lsp`, `ui`,
`app`, `ci`, `docs`. See [docs/COMMITTING.md](docs/COMMITTING.md).
- **One concern per branch.** `main` is protected: PR required, linear history, no
force-push. See [docs/BRANCHING.md](docs/BRANCHING.md).
- **4-space indent, 120 columns.** Enforced by `.swift-format`.
- **`CodeEditorCore` imports `Foundation` only** — no SwiftUI, no AppKit. That is what makes
it testable without a window server, and what makes offset arithmetic testable at all.

## Traps that will bite

- `Document` is ambiguous inside modules that import SwiftUI. Write `CodeEditorCore.Document`.
- Never key a dictionary or set by `URL` where the path is what matters. See
[MEMORY.md #3](docs/MEMORY.md).
- Do not add `ObservableObject` to anything. It is `@Observable` throughout.
- Do not give a `@MainActor` class a `deinit` that touches its state.
- `SourceEditor` takes a `Binding<String>`; there is no push path from `Document` to the
view. See [MEMORY.md #4](docs/MEMORY.md).

## Before you call it done

- [ ] `swift build` passes
- [ ] `swift test` passes
- [ ] `swift-format lint --strict` clean
- [ ] Behaviour change has a test; bug fix has a test that fails without the fix
- [ ] New public APIs have doc comments that state the contract
- [ ] The `.md` files above are still true

That last item is not a formality. It is the difference between this repository and one
where the next hour is wasted.
87 changes: 38 additions & 49 deletions PROJECT_PLAN.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,48 @@
# CodeEditor MVP — Project Plan
# Project plan

## Current state
Superseded by the documents in [`docs/`](docs/). This file is kept only so old links resolve.

The MVP is feature-complete and building green. `swift build` and `swift test` (35 tests)
both pass. `PROJECT_PLAN.md` originally described an eight-week roadmap whose Phase 1 goal
was to hand-roll syntax highlighting; that was replaced by
[CodeEditSourceEditor](https://github.com/CodeEditApp/CodeEditSourceEditor), which provides
the text view, tree-sitter highlighting, gutter and undo handling out of the box.

Shipped:

- File explorer with lazy recursive tree, create / rename / delete
- Editing via `SourceEditor` with tree-sitter highlighting for ~25 languages
- Document tabs, dirty tracking, save with untitled-location prompt
- Line-ending detection and preservation
- Embedded shell terminal with history and 2000-line scrollback
- Three themes with persisted editor preferences
- Menu commands and keyboard shortcuts
- `CodeEditorLSP` transport with real Content-Length framing (not yet wired to the UI)

## Next up

| Issue | Scope |
| Looking for | Read |
|---|---|
| LSP completion | Connect `LSPClient` to `SourceEditor` via a `TextViewCoordinator`; fuzzy-filtered popup, Tab/Enter to accept |
| Diagnostics | Consume `textDocument/publishDiagnostics`; underline plus gutter markers |
| Hover and go-to-definition | Tooltips and ⌘-click navigation using `textDocument/hover` and `definition` |
| Settings panel | Persisted preferences UI replacing the current menu-only controls |
| What this project is for | [docs/IDEA.md](docs/IDEA.md) |
| What works and what does not | [docs/CURRENT_STATE.md](docs/CURRENT_STATE.md) |
| Versions and dependency rationale | [docs/STACK.md](docs/STACK.md) |
| Module boundaries and data flow | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) |
| How work gets done | [docs/PROCESS.md](docs/PROCESS.md) |
| Constraints worth knowing before touching anything | [docs/MEMORY.md](docs/MEMORY.md) |
| Branch and commit conventions | [docs/BRANCHING.md](docs/BRANCHING.md), [docs/COMMITTING.md](docs/COMMITTING.md) |

The original eight-week roadmap planned to hand-roll syntax highlighting in Phase 1.
CodeEditSourceEditor provides it, so that work is gone and the remaining plan is six issues
tracked in GitHub, ordered in [docs/CURRENT_STATE.md](docs/CURRENT_STATE.md).

## Roadmap

| # | Issue | Scope |
|---|---|---|
| 1 | [LSP completion](https://github.com/Yan123-tech/code-editor/issues/1) | Connect `LSPClient` via a `TextViewCoordinator`; fuzzy-filtered popup, Tab/Enter to accept |
| 2 | [Diagnostics](https://github.com/Yan123-tech/code-editor/issues/2) | Consume `textDocument/publishDiagnostics`; underline plus gutter markers |
| 3 | [Hover and go-to-definition](https://github.com/Yan123-tech/code-editor/issues/3) | Tooltips and ⌘-click navigation |
| 6 | [External change detection](https://github.com/Yan123-tech/code-editor/issues/6) | Reload clean files, prompt on dirty ones |
| 5 | [PTY terminal](https://github.com/Yan123-tech/code-editor/issues/5) | Real pseudo-terminal, ANSI parsing, SIGINT forwarding |
| 4 | [Settings panel](https://github.com/Yan123-tech/code-editor/issues/4) | Replace menu-only preference controls |

## Module boundaries

```
CodeEditorCore (no dependencies)
CodeEditorThemes (no dependencies)
CodeEditorTerminal (no dependencies)
CodeEditorLSP (no dependencies)
CodeEditorUI → Core, Themes, Terminal, LSP, CodeEditSourceEditor
CodeEditorApp → UI, Core, Themes, Terminal, LSP
```
## Quality gates

`CodeEditorCore` must stay UI-free so it remains testable without a window server.
- [x] Builds with no warnings
- [x] `swift test` passes (35 tests)
- [x] `swift-format lint --strict` clean
- [ ] CI builds the package — blocked, see [docs/MEMORY.md](docs/MEMORY.md#1-ci-cannot-build-this-package-do-not-try-to-make-it)
- [ ] Completion works for Swift
- [ ] Diagnostics render
- [ ] No leaks in a 30-minute session

## Risks

| Risk | Mitigation |
|---|---|
| Source editor API churn (upstream is pre-1.0) | Pinned to `from: 0.15.2`; the `Theme.editorTheme` bridge in `Sources/CodeEditorUI/Sources/Editor/EditorTheme+Bridge.swift` isolates the surface we depend on |
| `sourcekit-lsp` is Xcode-toolchain specific | `LanguageServerRegistry.sourceKitLSPPath` probes known locations and returns `nil` rather than failing to launch |
| URL equality treats `/tmp/x` and `/tmp/x/` as distinct | `FileSystemManager` keys its cache on `standardizedFileURL.path` |
| Terminal uses pipes, not a PTY | Documented in `TerminalSession`; no job control or terminal echo |

## Quality gates

- [x] Builds with no warnings
- [x] `swift test` passes
- [ ] Completion works for Swift
- [ ] Diagnostics render
- [ ] No leaks in a 30-minute session
| Source editor API churn (upstream is pre-1.0) | Pinned `from: 0.15.2`; `Theme.editorTheme` in `EditorTheme+Bridge.swift` isolates the surface we touch. [MEMORY.md #8](docs/MEMORY.md) |
| `sourcekit-lsp` is Xcode-toolchain specific | `LanguageServerRegistry.sourceKitLSPPath` probes known paths and returns `nil` rather than failing to launch |
| URL equality treats `/tmp/x` and `/tmp/x/` as distinct | `FileSystemManager` keys its cache on `standardizedFileURL.path`. [MEMORY.md #3](docs/MEMORY.md) |
| Terminal uses pipes, not a PTY | Documented in `TerminalSession`, tracked as issue #5 |
| LSP is the largest module and unused | If issues 1–3 do not land, delete it rather than keep it aspirational. [CURRENT_STATE.md](docs/CURRENT_STATE.md) |
37 changes: 29 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,39 @@ leaves that `UI` composes.
| `` ⌃` `` | Toggle terminal |
| `⇧⌘L` | Toggle dark/light theme |

## Documentation

| Document | What it covers |
|---|---|
| [docs/IDEA.md](docs/IDEA.md) | What this is for, what it deliberately is not, design principles |
| [docs/CURRENT_STATE.md](docs/CURRENT_STATE.md) | What works, what does not, test coverage, next steps |
| [docs/STACK.md](docs/STACK.md) | Toolchain and dependency versions, with the reasoning for each choice |
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Module boundaries, data flow, concurrency, where coupling lives |
| [docs/PROCESS.md](docs/PROCESS.md) | Local gate, branching, PRs, definition of done, releasing |
| [docs/MEMORY.md](docs/MEMORY.md) | Constraints that are expensive to rediscover |
| [docs/BRANCHING.md](docs/BRANCHING.md) | Branch naming and the PR flow |
| [docs/COMMITTING.md](docs/COMMITTING.md) | Conventional Commits types and scopes |
| [AGENTS.md](AGENTS.md) | Instructions for coding agents working here |

`docs/MEMORY.md` is the one to read first. It records why CI cannot build this package, why
`FileSystemManager` keys on paths rather than `URL`s, and which source editor API is safe to
depend on — each of which cost real time to work out.

If a change makes any of these documents wrong, fixing the document is part of the change.
See [AGENTS.md](AGENTS.md).

## Roadmap

`CodeEditorLSP` has a working transport — real `Content-Length` framing, request/response
correlating by id, notification routing — and a `sourcekit-lsp` descriptor that resolves
Xcode's bundled binary. It is not connected to the editor yet. Planned, in order:

1. Completion popup with fuzzy filtering and keyboard navigation
2. Diagnostics overlay with gutter markers
3. Hover tooltips
4. Go-to-definition
5. Settings panel
Xcode's bundled binary. It is not connected to the editor yet.

See [`PROJECT_PLAN.md`](PROJECT_PLAN.md) for the full roadmap.
1. [Completion popup](https://github.com/Yan123-tech/code-editor/issues/1)
2. [Diagnostics overlay](https://github.com/Yan123-tech/code-editor/issues/2)
3. [Hover and go-to-definition](https://github.com/Yan123-tech/code-editor/issues/3)
4. [External change detection](https://github.com/Yan123-tech/code-editor/issues/6)
5. [PTY terminal](https://github.com/Yan123-tech/code-editor/issues/5)
6. [Settings panel](https://github.com/Yan123-tech/code-editor/issues/4)

## Contributing

Expand All @@ -122,6 +142,7 @@ See [`PROJECT_PLAN.md`](PROJECT_PLAN.md) for the full roadmap.

- Branching model and PR flow: [docs/BRANCHING.md](docs/BRANCHING.md)
- Commit types and scopes: [docs/COMMITTING.md](docs/COMMITTING.md)
- Full workflow: [docs/PROCESS.md](docs/PROCESS.md)

Before pushing, run `swift build && swift test` locally — CI checks formatting and syntax
only, for the toolchain reason described above.
Expand Down
Loading
Loading