Configuration
Read .jobops/config.json. If missing, stop with:
JOBOPS NOT CONFIGURED Run /jobops:setup to initialize your workspace.
Use config.directories.resume_source for the source folder root.
The canonical layout contract lives at {plugin_root}/skills/audit-source/source_layout.md. Read it before running checks — the contract evolves; do not rely on memory.
Flags
--deep— also run semantic checks (achievements without metrics, vague responsibilities, cross-file skill inconsistencies). Slower, more questions. Default off.--migrate-layout— interactively reorganize an existing folder into the canonical layout. Run once at adoption time. Refuses to run if layout already matches.--section=<path>— audit only the named subfolder (e.g.WorkHistory/). Default: whole tree.--dry-run— produce the gap report without prompting for fills or writing edits.
Your Task
Audit the source folder so downstream skills can rely on it as authoritative — no inference, no hallucination, no synthesized fields. Every gap is either filled with user-authored content or explicitly marked as known-incomplete.
The remaining sections (Step 1 through Step 5, and "What this skill MUST NOT do") follow.
Step 1: Layout check
Read {plugin_root}/skills/audit-source/source_layout.md for the canonical structure. Then walk config.directories.resume_source and compare.
For each REQUIRED file in the canonical layout, check existence. For each file in the source folder, check whether its path matches the canonical layout.
Produce a layout diff:
| Status | Canonical path | Found at |
|---|---|---|
| OK | Identity/Name.md | Identity/Name.md |
| MISSING | Identity/CurrentRole.md | (not found) |
| MISLOCATED | Technology/TechStack.md | Skills.md (root) |
Decision tree:
- All canonical-required files present AND no mislocated files, WITHOUT
--migrate-layout→ proceed to Step 2. - All canonical-required files present AND no mislocated files, WITH
--migrate-layout→ print "Layout already matches canonical contract; no reorganization needed." and stop. - Missing files OR mislocated files present, WITHOUT
--migrate-layout→ print the diff and stop. Tell the user: "Layout does not match canonical contract. Re-run with--migrate-layoutto interactively reorganize, or fix manually and re-run." - Missing files OR mislocated files present, WITH
--migrate-layout→ enter Step 1a (migration).
Step 1a: Migration (only with --migrate-layout)
Refuse to run if git status shows uncommitted changes in the source folder. Tell the user to commit or stash first.
For each MISLOCATED file:
- Display the current path, the proposed target path, and the first 5 lines of the file as preview.
- Use
AskUserQuestionwith options:Move to proposed path/Specify different target/Leave in place (mark as orphan)/Skip this file. - On confirm: use
Bashtogit mvthe file (preserves history). - Append a line to
<resume_source>/migration_log.mdrecording (timestamp, old path, new path, decision).
For each MISSING required file:
- Note in the migration log: file required but not present; user must create it (audit-source will block on this in Step 2 if not addressed).
After all moves are confirmed and logged, proceed to Step 2.
Step 2: Structural audit (deterministic — no LLM judgment)
Every check in this step is a literal pattern match against file content. If a check requires LLM interpretation, it belongs in Step 5 (semantic audit, behind --deep).
For each file in the canonical layout, apply the checks below. Each match (or miss) produces a gap record: { file, line, category, description, severity, suggestion }.
Identity/CurrentRole.md
| Check | Severity | Description if failed |
|---|---|---|
| Contains a level-1 or level-2 heading | blocking | No job title heading found |
Contains a line matching (?i)^company: OR a heading matching ^#+\s+.+\s+—\s+.+$ (canonical <Company> — <Title> em-dash pattern) |
blocking | No company identified |
Contains a line matching (?i)start[:\s]+\d{4}-\d{2} OR an explicit Status: Unemployed since YYYY-MM line |
blocking | No start_date in YYYY-MM format |
WorkHistory/NN_company_role.md (for each file)
| Check | Severity | Description if failed |
|---|---|---|
Filename matches ^\d{2}_.+\.md$ |
advisory | Filename does not follow NN_ ordering prefix |
| Contains a heading with company name and title | blocking | No role title heading |
Contains a line (?i)start[:\s]+\d{4}-\d{2} |
blocking | No start_date |
| Contains a line `(?i)end[:\s]+(\d{4}-\d{2} | present)` | blocking |
Contains a ## Responsibilities or ## Achievements heading |
blocking | No content sections |
For each line containing %, $, or \d+x, check if any of the 5 lines preceding contain a non-numeric context word (>3 chars) |
advisory | Numeric claim without nearby context |
Technology/TechStack.md
| Check | Severity | Description if failed |
|---|---|---|
| Contains at least one bullet, table row, or sub-heading | blocking | File has no enumerated skills |
| (cross-file, --deep only) Every skill word that appears in WorkHistory file headings or tech-listing lines also appears here | advisory | Skill in WorkHistory missing from TechStack |
Technology/Certifications.md
For each bullet or section in the file:
| Check | Severity | Description if failed |
|---|---|---|
Line contains a cert name AND issuer (or None as file content) |
blocking | Cert lacks issuer |
Line contains a date in YYYY-MM format OR explicit In-Progress |
blocking | Cert lacks date |
Line contains status Active/Expired/In-Progress |
blocking | Cert lacks status |
Preferences/Vision.md and AntiVision.md
| Check | Severity | Description if failed |
|---|---|---|
| File exists | blocking | Required preference file missing |
File is non-empty OR contains the single word None |
blocking | Preference file empty without explicit None |
Cross-file timeline checks
Sort all WorkHistory files by start_date. For each adjacent pair (file_a ends, file_b starts):
| Check | Severity | Description if failed |
|---|---|---|
file_b.start_date < file_a.end_date (date arithmetic, deterministic) |
advisory | Timeline conflict: roles overlap |
(file_b.start_date - file_a.end_date).days > 30 AND no gap explanation is documented in Preferences/ or Identity/ |
advisory | Unexplained gap > 30 days |
Also check Identity/CurrentRole.md vs the most recent WorkHistory entry: if CurrentRole says "currently" or "present" but the most recent WorkHistory file has an explicit end_date in the past, flag as advisory: "CurrentRole says 'currently' but most recent role has end_date < today".
Output
Build gaps[] as a list of { file, line, category, description, severity, suggestion }. Hand to Step 3.
Step 3: Present gap report
If gaps[] is empty, print:
✓ Source folder passes structural audit. No gaps found.
If --dry-run, print the table below and stop without prompting.
Otherwise, print the gap table:
| # | Severity | File | Line | Gap | Suggestion |
|---|---|---|---|---|---|
| 1 | blocking | WorkHistory/01_globex.md | (front-matter) | No start_date in YYYY-MM format | Add line: `Start: YYYY-MM` |
| 2 | advisory | WorkHistory/01_globex.md | L8 | "Reduced costs significantly" — no metric | Add quantification or rewrite |
| ... |
Group counts at the top: 5 blocking, 7 advisory.
Then use AskUserQuestion with the question:
How would you like to proceed?
Options (single-select):
Fix all blocking gaps interactively(recommended if any blocking present)Fix a specific gap by numberMark all blocking gaps as known-incomplete and continue(downstream skills will see incomplete-source warnings)Exit — I'll edit manually
Looping:
- Option 1: enter Step 4 with
pending_gaps = blocking_gaps. After processing all, ask again with the remaining advisory gaps and the same options. - Option 2: ask "Which gap number?" via free-form
AskUserQuestion, enter Step 4 with that single gap. - Option 3: write all remaining gaps to
<resume_source>/audit_log.mdas "acknowledged-incomplete" entries; proceed to Step 5. - Option 4: write current state to
audit_log.mdand Step 5 withgaps_fixed: 0.
Step 4: Interactive gap fill (propose-then-confirm)
For each gap in pending_gaps:
4a: Display context
Read the relevant file. Display the line at gap.line plus 3 lines of context before and after. If the gap is "file missing entirely," display the canonical path and a one-line description of what the file should contain (from source_layout.md).
4b: Elicit the fact via AskUserQuestion
Question phrasing is literal and narrow. Never lead with categorical enums. Never suggest a value from the LLM's prior knowledge of the candidate.
Examples by gap category:
- Missing date: "What is the start date for your role at Acme? (format: YYYY-MM)" — free-text input. Validate the response matches
^\d{4}-\d{2}$before proceeding. - Missing certification field: For "AWS Solutions Architect — no issuer/date/status", ask three separate questions: "What is the issuer?" / "When did you obtain it? (YYYY-MM)" / Multi-select:
Active/Expired/In-Progress. - Vague achievement (advisory): "The line reads: 'Reduced costs significantly through restructuring'. Would you like to:
Add a specific metric/Add a timeframe only/Leave as-is (acknowledge advisory)?" - Timeline gap: "There's an unexplained 14-month gap between your role at Initech (ending 2022-11) and Globex (starting 2024-01). What was happening during this time? (Free text — or type 'skip' to mark as acknowledged-incomplete.)"
If the user types skip or selects "Leave as-is", record the gap as acknowledged-incomplete and move to the next gap.
4c: Propose the edit
Construct the exact edit as a unified diff:
--- WorkHistory/01_globex.md
+++ WorkHistory/01_globex.md
@@ -2,3 +2,4 @@
# Globex Corp — VP, Engineering
+Start: 2022-12
End: 2024-08
Industry: FinTech
Display the diff to the user.
4d: Confirm via AskUserQuestion
Single-select question: "Apply this edit?"
Apply— write the edit using theEdittool.Modify— re-ask Step 4b with the user's choice as default; loop back to 4c.Skip— discard, record as acknowledged-incomplete.
4e: Apply and log
On Apply:
- Use the
Edittool to make the change. - Append to
<resume_source>/audit_log.md:
## YYYY-MM-DDTHH:MM:SSZ — Gap fix
- File: WorkHistory/01_globex.md
- Line: (front-matter)
- Gap: No start_date in YYYY-MM format
- User input: 2022-12
- Edit applied: yes
Never batch edits across gaps. Each gap is a separate Edit call with a separate confirmation. The user owns their resume; the tool's job is to make the user's intent explicit and durable.
4f: Loop or exit
After each gap is resolved, loop to the next pending gap. After all pending gaps are processed, return to Step 3 to offer the next decision (e.g., switch from blocking to advisory).
Step 5: Audit summary and machine state
Write .jobops/source_audit.json:
{
"schema_version": "1.0.0",
"audit_timestamp": "<ISO8601>",
"checks_run": ["structural", "semantic"],
"flags_used": ["--deep"],
"gaps_found": 12,
"gaps_fixed": 9,
"gaps_acknowledged_incomplete": 3,
"remaining_blocking_gaps": 0,
"files_edited": [
"WorkHistory/01_globex.md",
"Technology/Certifications.md"
]
}
If --deep was used, add "semantic" to checks_run.
If remaining_blocking_gaps > 0, print a final warning:
⚠ Audit complete with N blocking gaps remaining. Downstream skills (resume, cover letter, pitch deck) may produce incomplete or inaccurate output until these are addressed. Re-run /jobops:audit-source to continue.
Acknowledged-incomplete gaps:
: — ...
If remaining_blocking_gaps == 0, print:
✓ Source folder passes structural audit. Downstream skills can rely on the source as authoritative.
Step 6 (optional, --deep only): Semantic audit
Run additional LLM-driven checks that the user can disagree with:
- Vague responsibilities: bullets under "Responsibilities" with no scope (no number, no scale, no named system). Flag advisory.
- Unquantified achievements: bullets under "Achievements" with no metric (no %, $, count, timeframe). Flag advisory.
- Cross-file inconsistency: skill mentioned in WorkHistory but missing from TechStack (and vice versa). Flag advisory.
Each flag goes through the same Step 4 propose-then-confirm flow with its existing Apply / Modify / Skip options. All --deep flags are advisory (never blocking). When the user selects Skip for a semantic-audit flag, record it in audit_log.md as user disagreed with semantic flag (rather than the generic acknowledged-incomplete used for structural skips), so the dissent is auditable.
What this skill MUST NOT do
These are not suggestions. Each one is a documented failure mode from baseline testing (see tests/baseline_broken_folder.md).
- Never edit a source markdown file without per-edit user confirmation. Even if the user said "fix all blocking gaps interactively" in Step 3 — that authorizes the flow, not specific edits. Every edit goes through Step 4d.
- Never infer values to write into source files. If Globex has no
start_datein the source, do not fill it from "the gap before Globex started must equal the end of Initech." The user must state it. Period. - Never fill an enum field where the source doesn't have a verbatim anchor. Baseline trials populated
company_size: "Enterprise"based on a VP title. That is the exact failure mode this skill exists to prevent. - Never silently move files. Migration (Step 1a) is opt-in via
--migrate-layoutand per-file confirmed. - Never run semantic checks without
--deep. Default mode is fast and deterministic. - Never delete content from source files. Only insert missing fields or correct verbatim factual errors the user explicitly directs.
- Never narrow a range the user hasn't narrowed. "High six figures" stays as "high six figures" unless the user provides a specific number when prompted. Do not store
compensation_target: 850000from ambiguous prose. - Never assume
Activestatus for a certification without a date or explicit user statement. Status enums require source evidence. - Never proceed past Step 1 if the layout check fails without
--migrate-layout. Tell the user and stop.
Red flags — STOP and re-read this section
If you find yourself thinking any of the following while running this skill, you are about to violate the rules:
| Thought | Reality |
|---|---|
| "The user obviously means X — I'll just fill it in" | If it's obvious, ask anyway. The cost of asking is one question. The cost of guessing wrong is a fabricated resume. |
| "This is just an advisory gap, it doesn't really matter" | Advisory gaps still produce downstream confabulation if filled silently. Ask or skip — never quietly invent. |
| "The user said 'fix all gaps' — I have authorization" | They authorized the flow, not the content. Every edit needs its own confirmation. |
| "I can compute this from other fields" | Date arithmetic is fine. Categorical inference (company_size from title, proficiency from time spent) is not. |
| "Saying 'I don't know' is unhelpful" | Saying "I don't know" is the most helpful thing this skill can do. Confabulation is the failure mode. |