# ThoughtFrame Eclipse plugin — TODO

Everything the agent can do to the IDE is a **command**: a named action with an
implementation behind the workspace bridge. This is the list of commands to
implement, plus the plumbing still owed.

Two kinds, and the difference matters:

- **Model tools** — declared in `frames/tui/functions/*.json` and offered to the
  model, so it can choose to call them (`open`, `replaceSelection`).
- **Machine steps / hotkey actions** — not offered to the model; the FSM or the
  developer runs them (`organizeImports`, `format` are the machine's tidy-up
  after an edit). Same registry, different driver.

Most of these are Eclipse command ids run through `ide/command` (the model
pressing the button the IDE already ships, dialogs and undo included). Where a
command id is uncertain it is marked **(?)** — verify in the IDE before wiring.

---

## Implemented

- [x] `ide/open` — open a workspace file, optionally reveal a line
- [x] `ide/peek` — read a file window (path, startLine, count) without opening it or moving the active editor; returns the text, headed by path/range/total
- [x] `ide/glob` — find files whose path matches a glob (`**/*.java`); all workspace projects, skips build/VCS folders
- [x] `ide/grep` — search text files for a literal or regex string, scoped or whole-workspace; returns `path:line: text`
- [x] `ide/write` — create or overwrite a workspace file; the host confirms first
- [x] `ide/console` — read the Eclipse consoles' buffered text (build/run/test output)
- [x] `ide/build` — build every project incrementally and return problem markers
- [x] `ide/runTests` — run the project's test command and return the output tail
- [x] `ide/replaceSelection` — replace a range, one undoable change
- [x] `ide/command` — run any workbench command id on the active editor
- [x] `ide/format` — format the whole active file (select-all, then Format)
- [x] `organizeImports` — `org.eclipse.jdt.ui.edit.text.java.organize.imports`
- [x] `format` — `org.eclipse.jdt.ui.edit.text.java.format`

## Editor / source actions

- [ ] organize imports on a *given* file, not just the active one
- [ ] add import — `org.eclipse.jdt.ui.edit.text.java.add.import`
- [ ] sort members — `org.eclipse.jdt.ui.edit.text.java.sort.members`
- [ ] clean up (the whole Source > Clean Up profile) — `org.eclipse.jdt.ui.edit.text.java.clean.up`
- [ ] toggle comment — `org.eclipse.jdt.ui.edit.text.java.toggle.comment`
- [ ] add / remove block comment — `org.eclipse.jdt.ui.edit.text.java.add.block.comment`, `…remove.block.comment`
- [ ] correct indentation — `org.eclipse.jdt.ui.edit.text.java.indent`
- [ ] generate getters and setters **(?)**
- [ ] generate `hashCode()` / `equals()` **(?)**
- [ ] generate `toString()` **(?)**
- [ ] generate constructor from fields **(?)**
- [ ] override / implement methods **(?)**
- [ ] quick fix (Ctrl+1) — `org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals` (interactive)

## Refactorings (LTK — programmatic, one undoable step)

- [ ] rename element — `org.eclipse.jdt.ui.edit.text.java.rename.element`
- [ ] move element — `org.eclipse.jdt.ui.edit.text.java.move.element`
- [ ] change signature — `org.eclipse.jdt.ui.edit.text.java.change.signature`
- [ ] extract method — `org.eclipse.jdt.ui.edit.text.java.extract.method`
- [ ] extract local variable — `…extract.local.variable`
- [ ] extract constant — `…extract.constant`
- [ ] extract interface — `…extract.interface`
- [ ] extract superclass — `…extract.superclass`
- [ ] inline — `org.eclipse.jdt.ui.edit.text.java.inline`
- [ ] pull up / push down — `…pull.up`, `…push.down`
- [ ] introduce parameter / factory / indirection — `…introduce.parameter`, `…introduce.factory`, `…introduce.indirection`
- [ ] use supertype where possible — `…use.supertype`
- [ ] infer generic type arguments — `…infer.generic.type.arguments`

Most of these open the IDE's own preview dialog. That is fine — the agent
presses the button, the developer confirms, the IDE does the transformation.
Running them programmatically (no dialog) is the alternative, via
`PerformRefactoringOperation`, when we want the machine to drive them.

## Navigation

- [ ] open declaration — `org.eclipse.jdt.ui.edit.text.java.open.editor`
- [ ] open type hierarchy — `org.eclipse.jdt.ui.edit.text.java.open.type.hierarchy`
- [ ] open call hierarchy — `org.eclipse.jdt.ui.edit.text.java.open.call.hierarchy`
- [ ] reveal in Outline / Package Explorer **(?)** — so the developer sees what the agent is looking at

## Search

- [ ] find references in workspace — `org.eclipse.jdt.ui.edit.text.java.search.references.in.workspace`
- [ ] find declarations in workspace — `org.eclipse.jdt.ui.edit.text.java.search.declarations.in.workspace`
- [ ] find implementors — `org.eclipse.jdt.ui.edit.text.java.search.implementors.in.workspace`
- [ ] find read / write access **(?)**

These want a structured result (list of matches as plain data) more than the
IDE's Search view, so the model can reason about them.

## Build and verify (the oracle)

- [ ] build project / workspace — `org.eclipse.ui.project.buildAll`, or `IProject.build` for one project
- [ ] problems for a file / project — markers as plain data (message, severity, symbol)
- [ ] show the Problems view / jump to next problem **(?)**
- [ ] run JUnit tests — a launch configuration, not a command id; results as structured data
- [ ] run / debug last launch — `org.eclipse.debug.ui.commands.RunLast`, `…DebugLast`

## Workspace / files

- [ ] save / save all — `org.eclipse.ui.file.saveAll`
- [ ] revert file — `org.eclipse.ui.file.revert`
- [ ] refresh from disk — `org.eclipse.ui.file.refresh` (needed if the engine ever writes bytes directly)
- [ ] create file / class — wizard, or a custom action writing through the Java model
- [ ] delete file
- [ ] compare with HEAD / show diff — for reviewing a proposal before applying

## Git (EGit)

- [ ] stage / commit — `org.eclipse.egit.ui` commands **(?)**
- [ ] diff working tree vs HEAD
- [ ] branch / checkout — one per agent attempt, mirroring the student-sandbox model

## Debug

- [ ] toggle breakpoint — `org.eclipse.debug.ui.commands.ToggleBreakpoint`
- [ ] step over / into / return, resume, terminate — `org.eclipse.debug.ui.commands.*`

---

## How to add one (the recipe)

1. `frames/<family>/functions/<name>.json` — the schema, if the model should call it.
2. **Register the name in `frames/<family>/ai/framemessage.xconf`** — `llm-functions` is an
   allow-list, split on commas. `resolveAllowedFunctions` returns exactly those names, and
   `deepseek.html` loads `frames/<family>/functions/<name>.json` for each. A schema file that
   is not named there is never sent to the model — the folder is not scanned.
3. `frames/<family>/actions/<name>.html` — the response template (`$actionresult` / `$error`).
4. `frames/<family>/actions/<name>.xconf` — one `<path-action name="IdeModule.<name>"/>`.
5. `IdeModule.<name>(WebPageRequest)` — read the args, `invoke(inReq, "<name>", "ide/<name>", args)`.
6. `EclipseWorkspaceBridge.invokeAction` — the host verb for `ide/<name>`.

That's all. `TuiModule.runTool` runs `actions/<name>` directly and returns its rendered
output as the tool's `function_response` — the function name IS the action name, so no
`session.groovy` handler is needed just to return data. An action that renders `$error`
still returns as data. Arguments arrive as page values on the action request, keyed exactly
as the schema's property names (camelCase matters): the module reads them with `value(inReq,
"<name>")`.

A frame only needs a `thought:<name>` handler when it wants to *transition* on a tool; for
that, have the action fire its `ide:<name>` observation (which `IdeModule.invoke` does) and
listen for that.

Conversions, code conventions: fields `protected` not `private`, no `static`
fields (constants included), everything accessed through getters. `FrameViewer`
still needs this sweep.

---

## Plumbing owed

- [ ] Stop `transition()` firing its event from inside the pipeline states — it
      re-enters a frame we hold, which is the `Could not acquire lock` noise.
      Set the state directly in those states.
- [ ] Make the pipeline declarative on the frame: the frame declares its
      auto-advance states and a tick budget, so `pump` stops hardcoding
      `organize` / `format`.
- [ ] Seed the model's tool list from the developer's own keybindings
      (`IBindingService`) — the commands someone bound a key to are the ones
      they care about, and the list is personal and small.
- [ ] Record a tool's *outcome* in the conversation. Today `replaceSelection`
      records "proposed (awaiting the developer's confirmation)"; nothing records
      applied / rejected, so the model never learns what happened. The frame
      handler for `thought:replaceSelection` is the natural place.
- [ ] Render engine-side steps (`open`) in the transcript, not just the
      pump's steps.
- [ ] A failed action should stop or branch the machine. `action(...)` currently
      gets `error: …` back as page text, so the pipeline marches on regardless.

## Packaging

- [ ] Preference for the webapp root — `EclipseWorkspaceBridge.resolveWebappRoot`
      hardcodes `/home/ian/git/thoughtframe-core/thoughtframe/webapp`.
- [ ] Preference for the engine dir — `EngineIsland.resolveEngineDir` already
      honours `-Dthoughtframe.engine.dir`; make it a real preference.
- [ ] Thin bundle: drop `engine/` from `bin.includes` and load an external
      engine dir, instead of carrying 189 MB / 253 jars inside the plugin.
      The fat bundle stays the "mail it to someone" option, with
      `unpack="true"` so `engine/` stays a directory.
- [ ] A `feature/` project so an export produces an installable p2 update site.
