Automattic / Automattic/data-liberation-agent

`compare` and `publish` resolve a run directory differently, so `publish` will upload any folder

Open
#134 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.