Repository navigation
Conversation
|
I reproduced a remaining deletion in this PR with real TLC. From the repository root, with work=$(mktemp -d)
cp pstack/skills/statechart/scripts/test/upload.mmd "$work/upload.mmd"
node pstack/skills/statechart/scripts/statechart.mjs from-chart "$work/upload.mmd" --out "$work/chart"
printf 'keep this backup\n' > "$work/chart/tlc/Upload-backup.cfg"
node pstack/skills/statechart/scripts/statechart.mjs from-chart "$work/upload.mmd" --out "$work/chart"
test -f "$work/chart/tlc/Upload-backup.cfg"Both runs exit 0. The final check fails because the second run deleted the backup. Unrelated I opened a follow-up against your branch with an exact filename record and regression tests. With that change, normal reruns pass. The backup case exits 2 and leaves every output file unchanged. The compatibility cost is that existing nonempty |
|
Hey @kam-hak, you are right, and the repro is exactly the hole: Checked on my side: One thing I did not change and want to say out loud: a record names files that are replaceable, so a user who hand-edits |
…hind an owned name foreign() matched the OWN regex against immediate entry names only, so a user's tlc/notes.md, a folder named chart.mmd, or a folder named .DS_Store passed the check and publish() removed them with the previous output folder. The preservation contract from cursor#741 is that a run refuses files it did not write. Only a regular file under an owned name is the run's own. tlc/ is owned as a folder whose entries are the files this script writes there (*.cfg, *.out, *.dot, regions-proof.mmd, regions-all.mmd; TLC's metadir is in the system temp folder), checked one level down. A folder or link under an owned name is foreign and is reported by its path. Test covers tlc/notes.md, a folder named chart.mmd, a folder named .DS_Store, a symlink named chart.mmd (refused, target untouched), and a folder of only owned files passing to the next step. Fails on main. Harness tree regenerated. Fixes cursor#773.
… top of tlc/ cursor#791 moved a comparing run's TLC files into tlc/fixed/ or tlc/against/. A record of the top-level names alone would list the folder, and the next run would then report the folder as foreign and refuse. The record now holds every regular file under tlc/ as a relative path, and the check walks the same way: a folder is the run's own only while it holds something recorded, and a file inside it is reported by its full path (tlc/fixed/Pay-backup.cfg).
494ae7d to
b4f0c6e
Compare
Fixes #773.
Problem
foreign()matched theOWNregex against the output folder's immediate entry names and nothing else: no recursion, no entry-type check.publish()then removes the previous output folder withfs.rmSync(old, { recursive: true, force: true }). So three cases from the report pass the check and are deleted with the folder:tlc/notes.md, a user's file inside the ownedtlcdirectory;chart.mmd(an owned file name on a folder);.DS_Store.A root-level
notes.mdwas refused correctly. This contradicts the contract stated in #741: a run refuses files it did not write.Change
OWNnow describes top-level files only. Insidetlc/, each run records the exact filenames it wrote intlc/.written.json, and the next run treats anything not in that record (or any entry that is not a regular file) as foreign. An earlier revision of this PR matchedtlc/contents by extension (*.cfg,*.out,*.dot), which still let a rerun delete a user'sUpload-backup.cfg; @kam-hak reproduced that with real TLC and contributed the record-based check (commits 494ae7d, 726c902).foreign()reads entries withwithFileTypes, ownstlconly as a directory and checks its contents one level down, and treats anything that is not a regular file under an owned name (a folder, a symlink) as foreign, reported by its path (tlc/notes.md).publish()andrefuseForeign()are unchanged; the existing refusal message now names the nested path.The symlink note in the report is handled the same way: a link named
chart.mmdis refused rather than removed, and its target is untouched.Tests
scripts/test/statechart.test.mjs: one new test with five fixtures, each run asfrom-spec Pay.tla --out <folder>with a stubtla2tools.jarso the check runs before TLC would:tlc/notes.mdrefused, the file still present afterwards;chart.mmdrefused;.DS_Storerefused;chart.mmdrefused, target intact;tlc/) passes the check and stops at the next step (the missing mapping).Plus two from the follow-up: unrecorded TLC files and invalid or missing records are refused (runs without TLC), and TLC reruns replace recorded files, drop old rule files and keep unrecorded ones (needs TLC).
Compatibility cost: an output folder written before this change has no
tlc/.written.json, so a rerun into it with a non-emptytlc/is refused and needs a fresh--outfolder. The help text says so.Rebased onto
mainafter #791 (the Pele renderer port), which kept the pre-fixforeign(); the fix applies unchanged. #791 also moved a comparing run's TLC files intotlc/fixed/andtlc/against/, so the record now lists every regular file undertlc/by relative path and the check walks the same way; a file the record does not name is reported by its full path (tlc/fixed/Pay-backup.cfg), with a fixture for it.Fails on
mainon the first fixture.node --teston the file: 60 pass, TLC-dependent cases skip here as before.generate-pstack-harness-trees.mjs --checkis up to date.