The problem, in numbers
A matter accumulates files the way a desk accumulates paper: client uploads, email
attachments auto-filed from the inbox, scans, drafts, filings. The folder feature to tame
this already exists on v3, and the lawyers who use it use it seriously. But the production
data says most matters never get organised — and the bigger the matter, the less likely
anyone files anything.
16 → 2,277
median → max files per case on v2; one in ten cases crosses 100 files
23%
of 25–49-file v3 matters have folders — the adoption peak
~8%
at 50+ files, adoption collapses — exactly where organisation matters most
55–93%
of files get filed once a lawyer commits to folders: all-or-nothing behaviour
The shape of that adoption curve is the whole case for this feature. Filing climbs with
matter size until the backlog gets big enough that retro-organising becomes an afternoon's
work, and then lawyers give up: the cost of organising scales with the file count, the value
arrives later, and there's always something more urgent. The lawyers who do pay the cost file
nearly everything, which tells us the want is real; the collapse at 50+ tells us the price is
too high exactly where the payoff is biggest.
One more thing the production data hands us for free: lawyers who build folders by hand
independently converge on the same taxonomy — correspondence, drafts, client docs,
pleadings, fees & costs, notices, e-filing confirmations. Proposing a sensible default
structure isn't speculation about what lawyers want. It's literally what they already build,
when they can afford the time.
Lawyers don't need a new folder feature. They need someone to do the filing.
The design, in six decisions
Most of the plumbing exists: the VFS, the editable-surface registry, the folder CRUD, the
permission model. The decisions below are the parts that didn't, each chosen over a real
alternative.
1 · One batched edit surface, no new protocol, no new verbs
The VFS has no delete verb and no folder concept, and we add neither. All seven operations
— create, rename, recolour, reorder, delete, assign, unassign — travel as one batched payload
on a single server-fulfilled edit surface. The path puts a virtual collection
resource in the resource slot, so the existing parsers and registry dispatch in both repos work
untouched:
files://mat_7k
Matter-level read: folders, files, assignments. The grounding for every proposal.
→
files://mat_7k/folders/operations
The edit surface. "folders" is a virtual collection resource; "operations" is the field the registry dispatches on.
→
results[] + summary
Per-op status: applied · no_op · target_not_found · failed — with previousFolderId echoed per file.
Three path segments means zero dispatch-architecture changes: the same
(protocol, field) registry key the filled-form surface uses, one precedent over.
A full reorg of a 300-file matter is about ten operations, not three hundred:
mv is variadic (many files, one destination — its native POSIX shape), and
mkdir can carry the files that belong in it (mapping to matter-service's existing
transactional create-and-assign). One confirmed proposal, one write, one version of the truth
about what changed.
The operation names are deliberate: mkdir, mv, rmdir
— not create_folder, assign_files, delete_folder.
The VFS exists to cash in the model's filesystem priors, and the batch is just a script of
commands it already knows: moving files to the matter root unfiles them, renaming a folder is
mv, and rmdir refusing a non-empty folder is a guardrail the model
expects before reading a line of documentation. The two un-POSIX ops are recolour and
reorder (folder colour and manual sort order are UI metadata), and the one disclaimed prior is rm -r —
recursive delete deliberately doesn't exist.
2 · Propose first; only a plain "yes" executes
Chat is the entire interaction surface: no review modal, no diff UI. That puts weight on
the confirmation rule, so the skill pins it down hard. Lawrence proposes the structure
summarised (folders, counts, representative examples — full file-by-file listing on
request). Only an unqualified confirmation executes; "yes, but rename X" is a
modification, and modifications produce a revised proposal, never a partial execution. If the
file set changed since the proposal — uploads land mid-conversation all the time —
Lawrence re-reads before building the payload, files only what was proposed, and tells the
lawyer what arrived in the meantime rather than silently filing it.
3 · Operation semantics absorb the mess
Three concurrent writers already touch folder assignments in production: the files-page UI,
the Outlook add-in, and email auto-filing. The contract is built to be safe to retry and
boring under contention. Creating a folder whose title already exists (case-insensitive)
reuses it — deterministically the oldest, since nothing enforces unique titles. Assigning
a file already in place is a no_op, which makes a double-sent "yes" harmless.
Deleting a non-empty folder is rejected outright — rmdir semantics, exactly
what the prior predicts: emptying must be explicit in the same batch, so destructive intent is
visible in the payload. A failed operation doesn't abort the batch; the summary reports what
actually happened.
mkdir { "title": "correspondence" } → no_op · reused matfol_2a "Correspondence"
rmdir { "folderId": "matfol_9c" } → failed · folder not empty: mv contents out first
The two guardrails an agent hits most: title-match reuse instead of duplicates,
and no silent unfiling through a folder delete — rmdir refuses, like it always has.
4 · The same permissions as the files page, by construction
The surface never trusts the model with identity: the acting person comes from agent
context, and an LLM-supplied id is discarded and logged (the same prompt-injection defence the
filled-form surface shipped). lawrence-api validates that every folder and file id in the
payload belongs to the matter in the path, mints a user JWT for the acting lawyer, and calls
the same lawyer.* matter-service procedures the files page calls —
FIRM-side matter access, fails closed. There is no parallel folder logic to drift: one
resolver, two callers. The plan also hardens the underlying procedures to scope folder ids to
the authorised matter — a pre-existing gap that an agent passing ids around makes worth
closing at source, not just at the surface.
5 · Revert comes free with the snapshot
Folder assignment is metadata — a nullable column on the file row — so undo is
cheap if you kept the right notes. The agent already re-reads the matter immediately before
executing (the drift defence); that read doubles as the revert source. "Put it back" rebuilds
prior state from the snapshot plus the per-file previousFolderId echoes in the
results: recreate any folders the reorg deleted, map old ids to new, reassign, delete what the
reorg created. Scoped honestly: most recent reorg, this conversation, best-effort —
files the lawyer moved since are skipped and reported. And if compaction has summarised the
results out of context, Lawrence says revert is no longer available instead of reconstructing
from memory. No persisted operation log, no new storage; cross-session undo is named
follow-up work.
6 · A skill carries the judgment; prod data carries the taxonomy
The payload mechanics live in the surface documentation; the when and how to
reason lives in a file-organisation skill, mirroring the form-filling pair.
The skill encodes the protocol above plus the part no schema can: what a good structure looks
like. Its reference taxonomy is the one lawyers already converge on in production —
correspondence, drafts, client docs, pleadings, fees & costs, notices, e-filing
confirmations — as examples to adapt per matter, not a template to enforce. Matters with
idiosyncratic structures (they exist: we found folders named after paralegals) keep them;
incremental runs file new uploads into what's there rather than rebuilding.
The build, step by step
Dependency order across the two repos; platform-v3 lands first and is inert until called,
the agents side stacks on it, the chip ships last behind its own flag.
- Harden matter-service folder procedures. Scope folder ids (and
create-and-assign file ids) to the authorised matter in update, delete, assign and
create-and-assign — closing the cross-matter gap this feature would otherwise make
agent-reachable.
- Folder-aware state read. Matter-level
read on
files:// in lawrence-api returns folders with counts plus files with
assignments, lean enough for agent context.
- The folder-operations edit contract. Zod schemas, the dispatch branch,
id validation, lawyer-JWT execution through matter-service, per-op results with
previousFolderId echoes, palette-constrained colours, the ~50-op cap.
- The agent surface. New editable surface in platform-vfs mirroring the
filled-form precedent: registry entry, payload documentation, personId injection defence, a
client method shaped like
edit_filled_form.
- The file-organisation skill. Propose-confirm-execute protocol,
staleness and revert rules, summarisation guidance, and the prod-derived taxonomy as
reference material.
- The prompt chip. A flag-gated suggestion pill in the sidebar composer,
phrased as the prompt it sends — "Can you help me organise the files on this
matter?" — discoverability for lawyers who'd never think to ask.
What could go wrong
- Classification quality on opaque filenames. A matter full of
scan_0034.pdf gives names-and-metadata classification nothing to work with. The
agent's existing search and read tools can consult content before classifying; the skill
should prefer that over guessing, and the pilot will tell us how often it needs to.
- The confirmation gate is prose, not code. Nothing structural stops an
edit firing without a proposal turn — the gate lives in the skill. File names are
third-party content sitting right next to a write tool, so the pilot watches for
"edit with no prior proposal in the trace" in Langfuse as a cheap behavioural backstop.
- Revert fidelity under concurrency. Echoes are captured at pre-read; a
concurrent move in the seconds before execution makes the recorded inverse approximate.
Last-write-wins is the declared policy and skipped files are reported, but revert quality
degrades silently in that window.
- Very large matters. The state read has no pagination and v2 matters
reach 2,277 files. The op cap is fine (arrays keep batches small); the context cost of two
full reads per organise is the thing to measure on big fixtures.
- The sidebar gating gotcha. A request carrying
surface:
"sidebar" gets read-only tools by server-side filtering — the chip and the
sidebar must send requests without it, or clicks silently do nothing. Verified during
rollout, not assumed.
Rollout and what success looks like
Platform contract first, agents surface and skill stacked behind the existing per-user VFS
and skills flags, the chip behind its own flag: enable for pilot lawyers, watch the Langfuse
traces, widen. The folder feature has no product analytics, so success is measured where the
evidence came from — the warehouse. Today ~9% of 50+ file matters have folders and
roughly half their files are filed; this feature exists to move both numbers decisively, and
proposals that get confirmed rather than abandoned are the leading indicator.
After v1
- Proactive organisation. The separate proactivity project triggers the
same propose-confirm-execute loop from events (new uploads landing) instead of a request;
the surface, contract and skill ship ready for it.
- A persisted operation record. Cross-session undo and an audit trail of
agent reorgs; v1's in-session revert deliberately avoids new storage.
- "Organised by Lawrence" attribution in the files page and matter
activity, beyond the lawyer-attributed audit columns mutations already get.
- Next-steps suggestion. The prediction-service path for surfacing
"organise these files" at the right moment; the chip ships first because it's one component
behind one flag.
- Behavioural evals for the skill. The confirmation, staleness and revert
rules deserve an eval harness rather than manual smoke tests.
- First-class VFS verbs, batched by code. Promote
mv /
rmdir / mkdir from payload vocabulary to real VFS verbs —
gated on the harness adopting programmatic tool calling, because the script is the
batch executor: the agent writes a few lines that call VFS verbs as functions, executed in
one go. Until then, new mutation needs get surfaces like this one. Direction note in Notion
("Extending the VFS Verbs").
What we still don't know
- Whether agent-proposed structures are good enough that lawyers confirm them mostly
unedited — the gut says yes on the strength of the taxonomy convergence, and the pilot's
confirm-versus-revise ratio will say for sure.
- Product call: whether agent reorgs need visible activity-log entries
for compliance comfort, beyond database audit attribution. Deferred with the persisted
operation record, but worth a deliberate answer before broad rollout.