# thoughtframe-core — agent notes

This repo runs a live ThoughtFrame engine inside Eclipse, driven through the `tf` client
(a thin HTTP client; it finds the port in `~/.thoughtframe/instances/*.json`).

**Prefer `tf` over the shell** for work in this workspace — it's indexed, scoped to the
real workspace, and goes through Eclipse, so the IDE stays the source of truth. Prefer it
over shell `grep`/`find`/`ls`, and `tf write`/`tf replaceSelection` over direct FS edits.
Run `tf help` for the live list. Verb pages are grouped in subfolders (search/ read/
edit/ run/ debug/ agent/ engine/); the `tf` client maps names to folders, so you still
type `tf VERB`. The verbs:

Search (Eclipse JDT index)
  tf find name=…                     type declarations (e.g. *Manager)
  tf references class=… [method=|field=]
  tf implementors class=… [method=]  subtypes / overrides
  tf hierarchy class=…               supertypes + subtypes
  tf type-info class=…               fields, methods, supertypes
  tf source class=…                  the type's source

Read
  tf status                          dashboard: editor, problems, launches, tests
  tf projects | tf project name=… | tf projectState name=&op=open|close
  tf editors | tf selection | tf stat path=… | tf properties path=… | tf classpath project=…
  tf markers [severity=] | tf tasks | tf bookmarks op=list | tf console [name=] [lines=]
  tf tests op=runs | tf problems [path=…]
  tf glob pattern=… | tf grep query=… [path=] | tf peek path=… [startLine= count=]
  tf localpeek path=/abs/or/~/file [startLine= count=]   any host file, inside or outside the workspace
  (range reads with startLine/count — do not cat/sed whole files; raw dumps are a top token burn.
   A whole-file read is the exception, not the default: only when you genuinely need the entire
   reference surface (e.g. renaming every occurrence). Otherwise peek/localpeek the window you need.)
  tf git project=… op=status|log|branch|diff [path=]

Edit (through Eclipse — creates parents, auto-reveals)
  tf open path=… [line=] | tf close | tf save [all=true]
  tf write path=… text=… | tf replaceSelection path=… before="<exact text>" text=…
  (replaceSelection locators are exact content — before, or from+to head/tail anchors — not line numbers)
  tf delete | tf mkdir | tf moveFile path=&to= | tf copy path=&to=
  tf move class=&target= | tf rename class=&newName=      (Eclipse LTK refactoring)
  tf format | tf formatAll path=… | tf organizeImports | tf highlight … | tf refresh

Build / run / debug
  tf build | tf clean [name=] | tf run | tf runTests project=…
  tf launch op=configs|running|run|stop name=… | tf launchConfig op=delete name=…
  tf debug op=launch name=…          launch a config in debug mode
  tf debug op=targets|threads|variables&thread=&frame=
  tf debug op=resume|suspend|stepOver|stepInto|stepReturn     (step over = stepOver)
  tf breakpoints op=list|set|clear path=&line=    (set takes path + line; the type is derived)
  tf runCommand command=…            any workbench command id

Extend / misc
  tf reloadframeplugins | tf clearCache | tf errors [lines=]
  tf websearch query=… (needs a key) | tf webfetch url=… [format=text] | tf scratch
  tf thought op=add|search|delete|taxonomy …  (agent memory via the "thought" searcher)

Engine
  tf engine status | frame framepath=… | tick framepath=… | until … | runframe …
  tf engine frames op=neighbours|connect|near|here …   (frame graph; topics are frames)

Notes
- After editing engine Java the running engine is stale: check `tf errors` (Hot Code
  Replace failures land there), then restart the target (`tf launch op=stop` +
  `tf debug op=launch`). Better: draft it as a webapp Groovy page — that's live, no restart.
- `tf help [q=…] [verb=…]` is a compact cheat sheet (names by folder, params on
  demand). Use it instead of searching the full Code Mode tool catalog.
- For throwaway scripts, prefer a scratch Groovy page run in the engine (`tf scratch`)
  over shell one-liners: it runs in-process with `context` and `bench` in scope.
- Everything searchable goes through ONE interface — `Searcher` (`bench.getSearcher("type")`
  + `QueryBuilder`) — backed by the embedded OpenSearch node: frames, thoughts, git repos,
  notes, framememory/RAG. It is already wired; do NOT reverse-engineer the search layer.
  Query idiom, semantic `deepsearch`, and "add a type by copying
  `WEB-INF/base/tf-eclipse/system/data/fields/<type>.xml`" are in `tf help`. Copy the
  nearest example (`agent/notes.*` is the minimal one); deep-reading the framework is
  what makes agent context explode.
- If a capability looks missing or unwired and you're about to deep-read the framework to
  find out, STOP and ASK the user first. Don't spelunk; only the user knows what's already
  there, and guessing is what burns the context.
- Keep state in the graph, not just the conversation: recall with `tf thought op=search …`
  / `tf engine frames op=near framepath=topic/…` as you work, and write decisions to
  `topic/<slug>` after (`tags`/`status`; `status=parked` for measure-later items). Check it
  while you work, not only at the end.

## The Eclipse plugin project: keep it OUT of Gradle

The PDE plugin lives at `eclipse/` and must NEVER be listed in `settings.gradle`.
Buildship imports every project in `settings.gradle` and stamps it with
`org.eclipse.buildship.core.gradleprojectnature`, overwriting the hand-maintained PDE
metadata (`.project`/`.classpath`/`.settings`) and renaming the workspace project to the
Gradle name. Removing it from `settings.gradle` later does NOT undo that import - the
workspace entry stays until it is deleted and re-imported. (Seen twice now.)

Symptoms:
- plugin-side Java changes (e.g. `FrameViewer`) don't take effect after relaunching;
- the workspace project is named `eclipse` (a Gradle project) instead of `thoughtframe-eclipse`;
- the project's recorded natures show `gradleprojectnature`, not `org.eclipse.pde.PluginNature`.

Fix (Eclipse-side; cannot be done through `tf`):
1. Delete the workspace project `eclipse` - UNCHECK "delete project contents on disk".
2. File > Import > Existing Projects into Workspace > `~/git/thoughtframe-core/eclipse`
   -> imports as `thoughtframe-eclipse` with PDE nature.
3. Ensure `eclipse/` is not in `settings.gradle` and that
   `eclipse/.settings/org.eclipse.buildship.core.prefs` does not exist.
4. Clean + relaunch the Eclipse Application.

The Gradle split mirrors the classloader split: `eclipse-build/` is the Gradle subproject
that stages the island runtime; `eclipse/` is a plain, hand-maintained PDE project.

## Rendering: load from the engine, do not `setText`

Do not read pages out of the plugin bundle and inject them with `browser.setText(...)`.
That document has no origin, so any in-page asset (e.g. the logo) resolves to
`file:///...` and 404s, and it bypasses the engine (Velocity) entirely, so edits to the
webapp never show. Point the browser at the engine URL instead
(`http://127.0.0.1:<getPort()>/...`, via `setUrl`) and it renders from the webapp.
Longer term the chat/transcript should be a served page updated over the websocket, so
there is no per-turn `setUrl`/`setText` at all. The engine caches pages: after editing a
webapp page run `tf clearCache`.

## Edit through `tf`, never raw disk

Raw filesystem edits desync Eclipse's resource model - that is exactly what turned a stale
workspace import into a hard-to-see bug (the running plugin kept reloading old classes).
Use `tf write` / `tf replaceSelection` (JSON body for multi-line), then `tf refresh` if
you changed files another way.
