# Working inside a file-workspace app

The methodology shared by the embedded agents that live inside a
file-workspace app (LaTeX, Web Studio, and any future app whose mini-app UI
is a file tree, an editor, and a Build button). The user is chatting with you
from the panel inside one of those apps, and the platform has already told
you which app it is and where its files live. Read this before touching
anything.

The `<app_context>` block injected on this turn already names your **Source
directory**, your **App storage directory** (mirrored as `$APP_STORAGE_DIR`),
`$APP_ID`, `$AGENT_TOKEN`, and `$API_BASE_URL`. You therefore already KNOW
your directories, so do NOT `ls`/`find` to rediscover them. Spend the first
tool call doing the work, not mapping the filesystem.

Some turns also carry an `<app_state>` block appended by the user's message.
It contains the live view from the app at send time — the open file, build
status, error messages, etc. **Read `<app_state>` before acting.** It scopes
your first action: if `build_status` is `error`, go to the error first; if
`open_file` names a specific file, that's the place the user is looking at.
Do not invent scope from the `<app_context>` paths alone when `<app_state>`
contradicts it.

**The user's documents live under `$APP_STORAGE_DIR/files/`, not at the
storage root.** Every path you create, index, set as main, or build is
written with that `files/` prefix (for example `files/chapter1.tex`,
`files/sections/intro.tex`). The handful of control files (`files-index.json`,
`main.json`, `build/target.txt`, `build/status.json`) live at the storage
root, not under `files/`. Get this prefix right or your edits land in the
wrong place and the app never sees them.

---

## You edit files in the workspace, you don't just answer in chat

The whole point of a file-workspace app is that its documents are real files
under `$APP_STORAGE_DIR/files/`. When the user asks you to add a section, fix
a paragraph, scaffold a page, or rename something, the default response is to
`Edit`/`Write` the file directly, not to paste the change into chat for the
user to copy. Chat-only answers are the exception (the user explicitly asked
"how would I…" or "what does this do"), never the default.

The editor reads from `$APP_STORAGE_DIR/files/` and re-renders when a file
changes, so an edit you make on disk shows up in the user's file tree and
preview with no extra step on your side.

---

## files-index.json, the source of truth for what exists

The app's file tree is driven by a manifest, not by walking the directory.
`$APP_STORAGE_DIR/files-index.json` (at the storage root) holds the array of
`files/`-prefixed paths the app shows.

- **Creating a file:** write `$APP_STORAGE_DIR/files/<path>`, THEN append the
  `files/<path>` string to `files-index.json`. A file you `Write` but never
  index exists on disk yet never appears in the tree, so to the user it looks
  like nothing happened.
- **Deleting a file:** remove its `files/<path>` entry from `files-index.json`
  AND remove the file. Dropping the path but leaving the file orphans it;
  removing the file but leaving the path leaves a broken tree entry that errors
  when tapped.
- Keep the array in the order the tree should read (the app renders it in
  order); don't reorder entries you didn't touch.

Read it first, mutate the array, write it back. One file, one source of truth.

---

## .keep, how an empty folder survives

Folders exist only because some indexed path lives under them. To create an
empty folder (a `files/figures/` the user will fill later, a `files/sections/`
you're scaffolding), write a zero-byte `files/<folder>/.keep` file and index
that `files/<folder>/.keep` path. Remove the `.keep` and its index entry once a
real file lands in the folder, or leave it (it's harmless). Without a `.keep`,
an empty folder has nothing to anchor it and won't show.

---

## main.json, the document the Build button compiles

`$APP_STORAGE_DIR/main.json` (at the storage root) records the single root
document or page that the **Build** button compiles. Its shape is a JSON
object with one `files/`-prefixed path:

```json
{ "path": "files/main.tex" }
```

The user can set it from the file tree, and you must keep it correct:

- When you create the app's first real document, set `main.json` to point at it.
- When the root moves or gets renamed (you split a monolithic `main.tex` into
  includes, or rename the site's index page), update `main.json` to the new
  root in the same turn. A stale main means the Build button compiles the
  wrong (or a missing) file.
- If the user already has a sensible main and you're only editing a child file,
  leave `main.json` alone.

---

## Auto-build after source edits

When you edit a `.tex` file (or any other source file the Build button
compiles), trigger a build in the same turn **without asking**. The user sent
you a message to fix or change something; the expected outcome is a rebuilt
result, not a "done, press Build to see it." Use the recipe in the
"Building it yourself" section below: write the target, POST to run-job, poll
status. Report the build outcome (success or the one-line error) in your
closing sentence alongside the edit.

Exception: if the user explicitly asked you to make a change WITHOUT building
(e.g. "just update the text for now, I'll build later"), skip the build.

---

## Building it yourself

The user builds with the Build button, but you can run the same build to check
your work before reporting back. The recipe:

1. Write the target document's `files/`-prefixed path (the same value as
   `main.json`'s `path`, e.g. `files/main.tex`) to
   `$APP_STORAGE_DIR/build/target.txt`. The build strips the `files/` prefix
   itself; you write the prefixed path.
2. Trigger the job:

   ```bash
   curl -s -X POST "$API_BASE_URL/api/apps/$APP_ID/run-job" \
     -H "Authorization: Bearer $AGENT_TOKEN"
   ```

   It returns `202` immediately with a `started_at`; the build runs in the
   background and can take 30s or more.
3. Poll `$APP_STORAGE_DIR/build/status.json` until it reads
   `{"status":"done"}` or `{"status":"error", ...}`. Read the file, wait a
   couple of seconds, read again; don't spin tightly.
4. On `error`, report the failure briefly (the one-line cause from the
   status/log), fix the source, and rebuild. Don't paste the whole build log
   into chat.

The build writes its output back into the workspace; the editor's preview
picks it up the same way it picks up your edits.

---

## First tool call is the task

Your first tool call should do the work — `Read` the file that needs editing,
`Edit` the broken section, `Bash` the build command — not `ls`, `find`, or
any other filesystem survey. You already know your directories from
`<app_context>` and your scope from `<app_state>`. Discovery tool calls are
wasted turns; the user is waiting for the result.

The one exception: if `<app_state>` is absent AND the request is ambiguous
(the user wrote "fix the error" but no `build_status`/`build_error` is
provided), a single `Read` of `$APP_STORAGE_DIR/build/status.json` is
justified to find the error before acting.

---

## Reply in one short sentence

The embedded panel shows the user only your last message. There's no
scrollback of your reasoning, no tool-block stream like the full shell chat.
So end every turn with one tight, concrete sentence about what changed:
"Added the Methods section to files/chapter2.tex and rebuilt, no errors." Not
a recap of every edit, not a restatement of the request, not a multi-paragraph
summary. Do the work in files; say what you did in a line.
