* fix(reset): make the documents reset block POSIX so it runs under zsh
The block merged in #580 used the bash-only builtin
"shopt -s dotglob nullglob". Claude Code's Bash tool runs the user's
shell, which is zsh on macOS, where the line fails with "command not
found: shopt", and under set -e the subshell exits 127 before its
deletion loop: the reset reported success and deleted nothing. The
replay tests ran the block under bash only, so they stayed green.
Rewrite the block as POSIX shell: explicit directory names instead of
brace expansion, and
"find <dir> -mindepth 1 -maxdepth 1 ! -name .gitkeep -exec rm -rf -- {} +",
which lists hidden entries and nested folders without any glob setting.
The replay tests now run the block under every shell present (bash,
zsh, sh, dash) and guard against bashisms returning. The zsh and dash
subtests fail on master.
* changelog: place the #699 entry under [Unreleased]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Mads Lorentzen <madslorentzen_17@hotmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
04-job-evaluation.md's Language Gate and job-scraper/search-queries.md's
query-language generation both read "your Languages table" from
01-candidate-profile.md, but the skeleton /reset wrote left "## Identity"
empty, so after a reset /rank and /scrape looked for a table the file no
longer had.
Carry "### Languages" and the table's header and separator rows in the
skeleton. The test derives both rows from the shipped file and pins that
the placeholder data row is not reintroduced; it fails on master.
Follow-up noted on #532.
The full-file skeletons for 01-candidate-profile.md and
02-behavioral-profile.md started at the "#" title, while the shipped
files open with a "---" block carrying framework_version. Applied as
written, one /reset profile left both files failing
tools/check_framework_version.py ("missing 'framework_version' in
frontmatter") and invisible to tools/check_upstream_updates.py, which
records a configuration error for a file with no local version - the
fork update path every fork is sent through.
Say to keep the frontmatter block and replace only what follows, with a
note under "Profile reset" that the marker is framework data, never
candidate data. The version is not hardcoded into the skeleton, where it
would go stale on the next bump. A derived test applies each skeleton
the way the step says and asserts the shipped file's version still
parses out unchanged; it fails on master for both files.
* fix(reset): target the headings the shipped skill files actually have
Two of /reset profile's Step 3 targets had drifted from the files they
rewrite.
The 05-cv-templates.md step anchored on a section beginning
"**Profile statement templates", a line the guide has never contained
(its heading is "**Create 2-3 profile statement templates for your main
role types:**"), so the wipe found nothing: the user's role-tailored
profile statements, and any *[Used for: ...]* statements /setup Path A
extracted from archived applications, survived a reset that reported
success.
The 02-behavioral-profile.md skeleton used headings the shipped file
does not have ("Strongest Behavioral Traits", "How I Work Best", a
truncated "Growth Areas") and dropped "## Core Behavioral Drives" - the
assessment table /setup collects and /interview reads - so one reset
left the file's headings permanently different from every other fork's.
Anchor on the real heading and re-emit it in the replacement; carry the
shipped headings in order in the skeleton. 01-candidate-profile.md and
07-interview-prep.md were already correct. Two new tests derive both
checks from the shipped files, so a renamed heading fails until /reset
follows it; both fail on master.
* test(reset): place the heading guards above the __main__ guard so a direct run sees them
python tests/test_reset_command.py ran only the five old tests; unittest
discover imports the module and saw all seven, which is why CI was green.
Also drop the CHANGELOG's claim that /setup and /interview name the Core
Behavioral Drives table - neither does.
/setup Step 3 personalised cv/main_example.tex but never the LaTeX contact
blocks embedded in 05-cv-templates.md and 06-cover-letter-templates.md, the
two files /apply actually compiles from; 06 was not a Step 3 target at all.
Step 3.5 now names the 05 contact tokens, a new Step 3.6 covers the 06
contact line and signature, the completion summary lists 06, and /reset
restores both blocks instead of listing 06 as framework-only (the existing
/reset coverage test forced that half).
tests/test_changelog_structure.py checks [Unreleased] on every PR for
duplicate headings, unknown headings, orphan entries and conflict markers -
the #425 duplicate-heading shape that was fixed by hand at merge time.
Claude-Session: https://claude.ai/code/session_013fqqLgQSnwgWkv98twQhHi
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
/setup Step 3 populates six skill files; /reset profile cleared four.
04-job-evaluation.md was listed by name under "files NOT touched (they
contain framework rules, not candidate data)" while Step 3.4 writes the
user's match areas, career goals, energizing/draining tasks, financial
situation and schedule constraints into it - and ci.yml's
placeholder-integrity job already guards that file under "personal data
may have been committed". job-scraper/search-queries.md, which Step 3.8
fills with their job boards, role titles, domain keywords, city and
commute tiers, appeared nowhere in reset.md at all.
Both are tracked and unignored, so Step 1 asked the user to confirm a
wipe list that omitted them and Step 4 then reported a blank profile
while /rank kept scoring against the old skills and career goals and
/scrape kept running the old city and queries. Re-running /setup does
not necessarily clean them either: Path A skips files whose content is
"no longer placeholder text", and Step 3.8 is phrased as token
replacement, with no tokens left to replace.
Both files are now previewed and cleared, restoring their /setup
placeholders while preserving the scoring framework and the query
structure. 04-job-evaluation.md leaves the preserved list, which keeps
03-writing-style.md and 06-cover-letter-templates.md - the latter
correctly, since its [YOUR_NAME] tokens are LaTeX scaffolding Step 3
never writes to. CLAUDE.md and cv/main_example.tex stay outside the
profile scope, which reset.md:13 defines as skill files only; the
preview and Step 4 now say they still hold personal data instead of
implying a full wipe.
tests/test_reset_command.py gains a profile-scope guard beside its
documents-scope one, deriving the file list from /setup Step 3's own
headings rather than hardcoding it, so a future /setup target that
/reset forgets fails in CI. Against master the three cases fail on
exactly the defect: preview missing search-queries.md, execution
missing both, and the preserved list mislabelling 04-job-evaluation.md
as framework-only - the last of which a filename search alone would
have missed.
Closes#364
Co-authored-by: Cursor <cursoragent@cursor.com>
/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>
* refactor: fold /setup_docs into /setup as third onboarding path
- Auto-detect documents/ at /setup Step 0; offer three paths (documents
folder, single CV import, interview).
- Inline document-driven merge logic into setup.md as Path A: read-before-
write, additive vs. conflicting bucket merge with per-conflict prompts,
inference labeling for behavioral and style files, STAR-stub generation
instead of fabrication.
- Step 3 substeps for skill files skip when Path A populated them; non-
skill substeps (CLAUDE.md, cv/main_example.tex, search-queries.md)
always run. Path C interview preserved verbatim. /setup --section <name>
update flow preserved.
- Delete .claude/commands/setup_docs.md.
- Update /reset prompts to point only at /setup. Update documents/README.md
to reference /setup throughout. Update README.md to drop the standalone
/setup_docs section and add upskill/ to the skills tree.
- Remove the trailing comma left in .claude/settings.local.json after the
PR #6 revert (was technically invalid JSON).
Single onboarding entry point. documents/ folder convention unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(README): finish readme alignment for the /setup fold
- Update onboarding-paths tip to reflect three paths (was "Either"
before /setup_docs landed in PR #6).
- Add documents/ and upskill/ entries to the file tree, both relied
on by the new /setup Path A and by /upskill respectively.
- Add a brief "Other commands" section briefly describing /expand and
/upskill so users discover them without having to read individual
command files. /reset stays in the existing "Starting over"
subsection, now linked from the new section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds four contributions from @Michael-Bach:
- /setup_docs - document-driven profile population from a documents/ folder (CV, LinkedIn export, diplomas, references, past applications). Idempotent merge with explicit additive vs. conflicting buckets and per-conflict prompts.
- /reset - typed-RESET confirmation gate for clearing profile data and/or documents folder contents.
- /expand - additive competency enrichment from documents and public URLs already in the profile (GitHub repos, portfolio sites), with web-searched syllabus lookups for named courses and certifications.
- /upskill - skill-gap analysis vs tracked jobs (or single URL), produces a prioritized heatmap and learning plan with year-tagged WebSearch queries.
Also adds the documents/ folder convention with README and gitignore entries for personal output files.
Closes#6