mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 08:36:25 +00:00
fix(reset): include documents/postings/ in the documents scope
/reset's preview, delete block, and scope description all skipped documents/postings/ - the drop folder for hand-pasted posting text, documented in documents/README.md and protected as personal data by security_guards.py - and then asserted "The documents/ folder is now empty." The new test derives the folder list from the git tree, so any future drop folder fails it until /reset covers it. Review finding F26 (2026-08-19). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1c19f6c45f
commit
2036b97040
@@ -20,7 +20,7 @@ If `$ARGUMENTS` is empty or does not contain a recognized scope keyword, ask:
|
||||
>
|
||||
> - **`profile`** — Clears candidate data from the skill files (profile, behavioral, STAR examples, profile statements). The framework structure and writing rules are preserved. Use this to re-run `/setup` from scratch.
|
||||
>
|
||||
> - **`documents`** — Deletes all files you've placed in the `documents/` folder (CV PDFs, LinkedIn export, diplomas, references, past applications). The folder structure and `README.md` are preserved.
|
||||
> - **`documents`** — Deletes all files you've placed in the `documents/` folder (CV PDFs, LinkedIn export, diplomas, references, pasted job postings, past applications). The folder structure and `README.md` are preserved.
|
||||
>
|
||||
> - **`all`** — Both of the above.
|
||||
>
|
||||
@@ -68,7 +68,7 @@ The following files are NOT touched (they contain framework rules, not candidate
|
||||
|
||||
### If scope includes `documents`:
|
||||
|
||||
Use Glob to list all files present in `documents/cv/`, `documents/linkedin/`, `documents/diplomas/`, `documents/references/`, and `documents/applications/`. Present as:
|
||||
Use Glob to list all files present in `documents/cv/`, `documents/linkedin/`, `documents/diplomas/`, `documents/references/`, `documents/postings/`, and `documents/applications/`. Present as:
|
||||
|
||||
```
|
||||
## Documents reset will delete:
|
||||
@@ -85,6 +85,9 @@ documents/diplomas/
|
||||
documents/references/
|
||||
- [filename] or "(empty)"
|
||||
|
||||
documents/postings/
|
||||
- [filename] or "(empty)"
|
||||
|
||||
documents/applications/
|
||||
- [subfolder/filename] or "(empty)"
|
||||
|
||||
@@ -193,6 +196,7 @@ rm -f documents/cv/*
|
||||
rm -f documents/linkedin/*
|
||||
rm -f documents/diplomas/*
|
||||
rm -f documents/references/*
|
||||
rm -f documents/postings/*
|
||||
rm -rf documents/applications/*/
|
||||
```
|
||||
|
||||
|
||||
@@ -56,6 +56,13 @@ per-file diff commands.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`/reset documents` now clears `documents/postings/`** - the drop folder for
|
||||
hand-pasted job posting text was absent from the preview, the delete block, and the
|
||||
user-facing scope description, after which the command told the user "The `documents/`
|
||||
folder is now empty" - false whenever postings were present, and they are exactly the
|
||||
personal residue a reset exists to clear. A new `tests/test_reset_command.py` derives
|
||||
the folder list from the git tree, so any future drop folder fails the test until
|
||||
`/reset` covers it.
|
||||
- **`convert_salary_excel.py` no longer corrupts US/UK-formatted numbers 1000x** - the
|
||||
both-separators branch always assumed European locale, so a `"1,234.56"` cell was
|
||||
silently converted to `1.23456` and written into `salary_data.json`. The rule is now
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
"""Guards for /reset's documents scope.
|
||||
|
||||
/reset ends its documents pass by telling the user "The `documents/`
|
||||
folder is now empty." That statement is only true if every personal-data
|
||||
drop folder is actually covered by both the Step 1 preview and the
|
||||
Step 3 delete block. `documents/postings/` was missing from both while
|
||||
being documented in documents/README.md and protected as personal data
|
||||
by tools/security_guards.py (review finding F26, 2026-08-19), so a reset
|
||||
silently kept the user's hand-pasted job postings.
|
||||
|
||||
The folder list is derived from the repository tree, so adding a new
|
||||
drop folder under documents/ fails this test until /reset covers it.
|
||||
"""
|
||||
import re
|
||||
import subprocess
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent
|
||||
RESET = REPO / ".claude" / "commands" / "reset.md"
|
||||
|
||||
|
||||
def tracked_document_subfolders():
|
||||
"""Names of documents/ subfolders tracked in git (ignores local noise)."""
|
||||
out = subprocess.run(
|
||||
["git", "ls-files", "documents/"],
|
||||
cwd=REPO,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
).stdout
|
||||
folders = set()
|
||||
for line in out.splitlines():
|
||||
parts = line.split("/")
|
||||
if len(parts) >= 3: # documents/<subfolder>/<file...>
|
||||
folders.add(parts[1])
|
||||
return folders
|
||||
|
||||
|
||||
class TestResetCoversEveryDocumentsSubfolder(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.text = RESET.read_text(encoding="utf-8")
|
||||
self.folders = tracked_document_subfolders()
|
||||
# The tree must actually contain the folders this test is about,
|
||||
# or the assertions below would pass vacuously.
|
||||
self.assertGreaterEqual(len(self.folders), 5, self.folders)
|
||||
|
||||
def test_preview_lists_every_subfolder(self):
|
||||
missing = [
|
||||
f for f in sorted(self.folders) if f"documents/{f}/" not in self.text
|
||||
]
|
||||
self.assertEqual(
|
||||
missing,
|
||||
[],
|
||||
"reset.md's preview never mentions these documents/ subfolders, "
|
||||
f"so the user confirms a deletion list that omits them: {missing}",
|
||||
)
|
||||
|
||||
def test_delete_block_removes_every_subfolder(self):
|
||||
deleted = set(re.findall(r"rm -r?f documents/(\w+)/", self.text))
|
||||
missing = sorted(self.folders - deleted)
|
||||
self.assertEqual(
|
||||
missing,
|
||||
[],
|
||||
"reset.md's delete block has no rm line for these documents/ "
|
||||
'subfolders, yet the command then claims "The `documents/` '
|
||||
f'folder is now empty.": {missing}',
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user