Automattic / Automattic/data-liberation-agent
`compare` and `publish` resolve a run directory differently, so `publish` will upload any folder
- Dominant language
- TypeScript
- Stars
- 31
- Forks
- 3
- Avg merge
- 10h 14m
- Merged PRs (30d)
- 81
Description
Two of the three verbs take a directory and have to answer the same question — *is this a liberated run directory, or the `website/` directory inside one?* Each answers it separately, and they disagree.
**`resolvePublishDirectory`** in `src/ui/publish.ts` looks **down**. If the given directory contains both `capture-receipt.json` and `website/`, it publishes `website/`; otherwise it publishes the directory as given.
**`resolveCheckDirectory`** in `src/lib/fidelity/check.ts` looks down *and* **up**. Same nested case first, then a fallback that checks the parent for `capture-receipt.json` and treats the given directory as the website root. Failing both, it throws.
The divergence is observable:
| Argument | `publish` | `compare` |
|---|---|---|
| run directory | publishes `website/` | works |
| `/website` | publishes it | works, via the parent lookup |
| any other directory | **publishes it as a site** | throws with a useful message |
The third row is the sharp edge. `compare` refuses a directory that is not a liberated copy. `publish` will happily upload an arbitrary directory — including, say, a home directory — because absent a receipt it treats the argument as already being the site root.
This is one concept with two implementations, so the two definitions of "a liberated run" drift independently. It is also a third place that knows the receipt's shape: `check.ts` declares a private `CaptureReceipt` interface, `capture.ts` declares a private `CaptureInventory`, and `ui/publish.ts` sniffs for the file by name.
## Proposed change
1. One resolver in the core — `resolveRunDirectory( dir ): { runDir, websiteDir, receiptPath }` — used by `compare`, `publish`, and anything added later.
2. One exported `CaptureReceipt` type, owned by the module that writes it (`capture-export.ts`), imported by every reader.
3. `publish` refuses a directory that is not a liberated copy, with the same message `compare` already gives, and gains an explicit opt-out for the deliberate "publish this arbitrary folder" case if that is wanted.
## Acceptance
- `compare` and `publish` accept and reject exactly the same set of directories.
- `publish ~/` fails instead of uploading.
- The receipt shape is declared once.
---
*AI assistance: researched and written by Claude via Claude Code, by reading both resolvers and comparing their branches. Chris Huber orchestrated and reviewed the work and is responsible for what is filed here.*
Contributor guide
Research direction
Start by reading resolvePublishDirectory in src/ui/publish.ts and resolveCheckDirectory in src/lib/fidelity/check.ts, then inspect the receipt definitions in capture.ts and capture-export.ts. Trace the compare and publish entry points and existing rejection message; done means both commands accept and reject the same directories, arbitrary folders are refused by publish, and the receipt shape has one declaration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, security, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100