Skip to content

Commit e592f85

Browse files
donislawdevclaude
andauthored
preset: every file of a preset says what it is for (#140)
* preset: every file of a preset says what it is for A run from a preset writes manifest.instructions.md beside the manifest, named after it: the question the preset answers, how to read the four outcomes, and every file with its format, size, expected outcome and one or two sentences on why it is in the set. A run of files of one target is one entry. Written from the manifest alone, by one function the command line and the window share, so both leave the same directory behind. The sentences come from a new optional recipe key, purpose, carried to files[].purpose in the manifest. A plain recipe key rather than something a preset passes around the recipe, because an ejected preset has to produce what the preset does (PR5). It takes no part in the seed, so no generated byte moves. It does enter the canonical recipe, so the pinned eject sums and the recipe_hash of every run from a preset move once - the owner's decision. All 140 targets of the six presets have one. The name is reserved before any target can take it, instructions already in the directory refuse the run before its first file, and a name too long for a file system is refused on the manifest's box. Instructions that cannot be written are said and leave no claim behind, and the run stands. verify does not count them as extra, cleanup --with-manifest removes them first, and a manifest naming anything but a plain name beside it is not acted on. The window offers Open instructions beside Open manifest, from one type for both buttons, and the batch screen has a Purpose box among the manifest notes, which moved into a type of their own to keep the batch under its field ceiling. cli/generate.go and preset/uploadset.go were split by what their parts do, and the file ceiling came down to 401. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * guard: every box of the manifest notes is looked for with a value of its own The same text went into every box, so once the purpose joined the kind of case, a kind of case that stopped reaching the manifest was still found - in the purpose. The mutation runner said NOT CAUGHT about a proven guard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * guard: the purpose keeps to a text box, and the flush is read where it happens Two guards were red on every system. The purpose box took the whole row of the batch's notes, and only a path is allowed the row - it is now a text box like the kind of case beside it, and the guard names it so a screen that stops drawing it is red. The manifest is written through writeClaimed since the instructions came to share it, so the durability guard reads the flush there and first asks that writeOver still goes through it. The line said when the instructions could not be written claimed the files were complete. It is also said after a stopped or partly failed run, so it now says only what is true there: the manifest was saved and holds the same facts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cleanup: the list before --yes names the manifest and the instructions too With --with-manifest the list printed without --yes named only the files the manifest lists, and --yes then removed the manifest and the instructions beside it as well - the manifest since there was a flag for it, the instructions since this branch. The list now ends with both, or with why they would stay: a file that stays, or instructions somebody already deleted. The run with --yes names them once they are gone, and --json carries them in a new record list in both reports, so files, removed, kept and would_remove still count only what the manifest lists. A record that cannot be removed now ends with its report on stderr like any failed run's, where it used to end with none. The run's settings travel as one value, which takes applyCleanup from nine arguments to three - it was the widest signature in the tree - and the ceilings follow it down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cleanup: instructions not named after the manifest are left alone A manifest is a file somebody can edit, and one whose run.instructions named the instructions of another run in the same directory had cleanup --with-manifest remove them - measured. cleanup now takes the instructions only when they are named after the manifest it was given, and reports any others as kept, with why, in the list before --yes and in the run. A manifest renamed after its run keeps working the same way: its files and the manifest go, its instructions stay and are named. The window's line about instructions it could not write now escapes a character nobody can see, in the path and in the system's sentence that repeats it, as the command line does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * changelog: cleanup takes only the instructions named after its manifest Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 4479d9b commit e592f85

50 files changed

Lines changed: 2199 additions & 465 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CHANGELOG.md‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ because it turns other people's test suites red.
1616

1717
### Changed
1818

19+
- **`tfg preset eject` writes a `purpose` line for every target, so an
20+
ejected recipe and the `recipe_hash` of every run from a preset differ from
21+
0.3.0.** The recipe carries the purposes so that an ejected preset still
22+
produces exactly what the preset does. The bytes of every generated file
23+
are unchanged. A pipeline comparing `recipe_hash` across tool versions will
24+
see a new value once.
25+
1926
- **A file name longer than 255 bytes is refused before anything is written,
2027
on every system.** Linux stores at most 255 bytes in a name, while Windows
2128
and macOS count characters, so a name of 200 Chinese or Japanese characters
@@ -307,6 +314,31 @@ because it turns other people's test suites red.
307314

308315
### Added
309316

317+
- **Every preset now says what each of its files is for.** A run from a
318+
preset writes `manifest.instructions.md` beside `manifest.json`: the
319+
question the preset answers, how to read accept, reject, sanitize and
320+
unspecified, and then every file - its name, format and size, what your
321+
system is expected to do with it and one or two sentences on why it is in
322+
the set. Many files of one kind, such as the fifty of a mass upload, are
323+
one entry. The file is named after the manifest, so `run2.json` gets
324+
`run2.instructions.md`, and it is written only when some file has a
325+
purpose - a plain `tfg generate --format png` writes none. `generate`
326+
prints `instructions:` under `manifest:`, `verify` does not count the file
327+
as extra, and `cleanup --with-manifest` removes it with the manifest - only
328+
when it is named after that manifest, so an edited or renamed manifest
329+
never takes instructions that may belong to another run. A
330+
run into a directory that already holds instructions of that name is
331+
refused before anything is written. If the file cannot be written, the run
332+
says so and does not fail over it, because the manifest was saved and
333+
holds the same facts.
334+
335+
- **A `purpose` for every target of a recipe.** One or two sentences on what
336+
the files are and why they are in the set. They reach `files[].purpose` in
337+
the manifest and the instructions beside it, and change no byte of any
338+
file. The batch screen has a `Purpose` box among the manifest notes of each
339+
batch, and the window offers `Open instructions` beside `Open manifest`
340+
after a run that wrote them.
341+
310342
- **A preset for unusual file names: `filename-handling`.** It answers "will
311343
my system store, show and give back a file name it did not expect?" with
312344
fifty names in seven groups: scripts from Polish to Korean, names that look
@@ -520,6 +552,14 @@ because it turns other people's test suites red.
520552

521553
### Fixed
522554

555+
- **`tfg cleanup --with-manifest` says before it acts that the manifest goes
556+
too.** The list printed without `--yes` named only the files the manifest
557+
lists, and `--yes` then removed the manifest as well. It now ends with the
558+
manifest and the instructions beside it, or says why they would stay, and
559+
the run with `--yes` names them once they are gone. With `--json` both
560+
reports carry them in a new `record` list. `files`, `removed`, `kept` and
561+
`would_remove` still count only what the manifest lists.
562+
523563
- **A report shows a character nobody can see in a file name as an escape.**
524564
`verify`, `cleanup`, the notes of a run, every error message and the
525565
refusals in the window printed such a character as it was, in a file name

‎README.md‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ for entry in manifest["files"]:
154154
assert not response.ok, entry["path"]
155155
```
156156

157+
A run from a preset also writes `manifest.instructions.md` - the same facts for
158+
a person to read: every file, what your system should do with it and why the
159+
file is in the set.
160+
157161
And where the right answer genuinely depends on your own policy, the manifest
158162
says `unspecified` instead of inventing one. A generator that guesses produces
159163
false failures, and a suite that cries wolf gets switched off.
@@ -315,8 +319,9 @@ tfg cleanup <manifest.json> [--yes] [--force] [--with-manifest] [--against <dir>
315319
Removes what the manifest lists and **nothing else**. Without `--yes` it deletes
316320
nothing and prints what it would remove. A file whose content changed since it
317321
was written is left alone and reported, because it may not be ours - `--force`
318-
removes those too. `--with-manifest` removes the manifest as well, once every
319-
file it lists is gone.
322+
removes those too. `--with-manifest` removes the manifest and the instructions
323+
beside it as well, once every file it lists is gone. The list printed without
324+
`--yes` names them too.
320325

321326
### `tfg recipe fmt`
322327

‎internal/audit/audit.go‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ func Claimed(m *manifest.Manifest) []manifest.File {
244244
// the manifest usually sits in the directory it describes, and a tool that
245245
// fails on its own output on the most obvious invocation is not usable.
246246
// Matched on the base name rather than the path, because a restored copy
247-
// carries its own copy of the manifest beside the files.
247+
// carries its own copy of the manifest beside the files. The instructions the
248+
// manifest names are its own output in the same way, and skipped the same way.
248249
//
249250
// A run that is cancelled reports what it managed to compare and says so
250251
// through the context error. Reporting "sound" on the strength of half a
@@ -309,7 +310,7 @@ func Verify(ctx context.Context, dir string, m *manifest.Manifest, skip string)
309310
// decided. walk builds these with filepath.Rel, which returns a clean
310311
// path, so a comparablePath here is a call that cannot be wrong -
311312
// removing it left this guard green. See the comment on comparablePath.
312-
if seen[p] || filepath.Base(p) == skip {
313+
if seen[p] || filepath.Base(p) == skip || (m.Run.Instructions != "" && filepath.Base(p) == m.Run.Instructions) {
313314
continue
314315
}
315316
unclaimed = append(unclaimed, p)

0 commit comments

Comments
 (0)