Write field notes from direct observation in two stages: short timestamped jottings taken during a session, expanded the same day into full notes that keep description, exact quotes, and reflection in separate sections, with a checker for missing headers, inference wording in description, unquoted verbatim lines, and late expansion. Use when a researcher needs a written record of what happened in a setting, based on watching and listening in that setting.
name: field_notes_basics description: "Write field notes from direct observation in two stages: short timestamped jottings taken during a session, expanded the same day into full notes that keep description, exact quotes, and reflection in separate sections, with a checker for missing headers, inference wording in description, unquoted verbatim lines, and late expansion. Use when a researcher needs a written record of what happened in a setting, based on watching and listening in that setting." metadata: { "includeInPrompt": true }
Field Notes Basics
Purpose
Field notes are the written record of an observation session: what the observer saw and heard in a setting, written down close enough to the event that the record can be trusted. The work has two stages. During the session the observer writes jottings: short, timestamped, keyword-level notes, plus any exact words captured in the moment. The same day, the observer expands those jottings into full notes in a fixed format. The expanded notes keep three things apart: description of what happened, verbatim words in quotes, and the observer's own reflection and inference. A note set where those three are mixed cannot be checked later, because a reader cannot tell what was observed from what was concluded.
Scope:
- diary-study-basics covers participants logging their own experience over a period, in their own words, on a schedule the researcher sets. This skill covers notes the observer writes. Material participants produce about themselves is diary data, not field notes.
- interview-transcript-analysis covers transcripts after interviews: coding recorded talk once an interview or focus group exists. Field notes are written from watching a setting, not from a recording of a conversation the researcher led. If a session is recorded and transcribed, working with that transcript belongs to that skill.
- note-taking-systems covers general personal notes: capturing and organizing information for later personal use. Field notes are a research record with a fixed format, a separation rule between description and reflection, and a same-day expansion deadline, kept so another reader can check what was observed against what was inferred.
- This skill is the observer's own notes from watching a setting, written during and just after observation. It starts at preparation for a session and ends at a checked set of expanded notes for that session.
- Verification note: the checker in the Operating Rules section uses only the Python standard library and was run on 2026-10-19 under Python 3.12.3 against its built-in fixture: 2 files holding 4 entries, 2 entries clean and 2 entries with planted faults. That run produced these totals: entries 4, entries missing a required header field 2, description lines with a flagged inference marker 3, verbatim lines not wrapped in quotes 2, and late expansions 1, with the one late entry showing a lag of 2 days. File mode was also run, with the fixture written out as 2 files and passed as arguments, and it produced the same totals. The self-test run passed. The method terms used in this skill, jottings, expanded notes, description kept separate from reflection, and same-day write-up, are described as plain practice. No claim in this skill is attributed to a named textbook, author, ethics board, or legal regime. Specific legal and ethics requirements for consent, recording, and storage vary by setting and jurisdiction and were not verified here.
Workflow
- Prepare before entering the field.
- Write the focus question for the session in one sentence: what this session is meant to observe, stated as activity, talk, or events in the setting. A session with no focus question produces notes about everything and evidence about nothing.
- Write down what counts as relevant before the session starts: the activities, roles, places, and kinds of talk the focus question covers, and what is out of scope. Decide relevance in advance. Deciding it while writing jottings means the busiest moments get the least thought.
- Learn the rules of the setting before the first session: where an observer may sit or stand, whether note-taking in view is accepted, whether any part of the setting is off limits, and who gave permission for the observation to happen. Permission from a gatekeeper, for example a manager, teacher, or organizer, is the starting point, not the whole of consent.
- Settle the consent basics for the people who will be observed. In settings where people can choose whether to take part, they need to know observation is happening, what the notes are for, and how to opt out. In public or open settings where individual consent is not practical, follow the rules of the setting and any ethics approval in force for the project, and record which basis the session ran under in the session log. The exact requirements differ by setting and place, and this skill does not state them. If the basis is unclear, settle it before observing, not after notes exist.
- Prepare the practical kit: a way to write jottings that fits the setting, a clock for timestamps, and the note format from step 2 ready to fill in. If writing in view would disturb the setting, plan short jotting breaks out of view instead, and accept shorter jottings as the cost.
- Set up the note format before the first session.
- Use one fixed format for every entry in a project. Each entry starts with a line containing only
## Entry. Header lines follow, one per line, in the form Field: value, with these fields: Date (the observation date, YYYY-MM-DD), Start (HH:MM), End (HH:MM), Setting, Observer (initials or a role label), and Note-Date (the date the expanded notes were written, YYYY-MM-DD).
- After the header, each entry has three sections, each opened by a heading line:
### Description, ### Verbatim, and ### Reflection, in that order. Every entry uses the same sections, even when a section holds a single line stating that nothing was captured for it.
- Decide the naming rule for people before the first session: pseudonyms or role labels by default, for example Host, Visitor 1, or a pseudonym used consistently across sessions. Real names go in the notes only when a name is needed for the research purpose and the basis for recording it is settled under step 1. Keep any list that links labels to real people in a separate file from the notes.
- Fix the quote rule: a line in the Verbatim section is a line wrapped in double quotes, holding words captured exactly as spoken. Words that were not captured exactly do not go in the Verbatim section. They are paraphrased in Description or dropped.
- Write one practice entry from a short test observation before the first real session, and run the checker from the Operating Rules section on it. A format fault found in practice costs nothing. The same fault found after a week of sessions costs a week of headers.
- Take jottings during observation.
- Keep jottings short: keywords, short phrases, counts, and names of roles, not full sentences. Jottings are memory triggers for the same-day expansion, not the notes themselves. An observer writing full sentences is watching the page instead of the setting.
- Timestamp jottings as you go: the time at the start of the session, then a time mark at each change of activity, speaker, or place, and at any moment the focus question points at. Exact minute accuracy matters less than a steady order of events with times attached.
- Record counts and concrete detail when they are cheap to capture: how many people are present, who is where, what objects are in use, and the order in which things happened. Counts taken in the moment cannot be recovered during expansion.
- Capture verbatim words exactly when wording itself matters: instructions, labels, repeated phrases, disagreements, and any line the focus question turns on. Write the words as spoken, mark them as quotes in the jottings, and note the speaker by label. If you did not catch the exact words, write a paraphrase and mark it as a paraphrase in the jottings. Do not upgrade a paraphrase to a quote during expansion.
- Mark gaps honestly in the jottings: a stretch you could not watch, a conversation you could not hear, a time you left the setting. A marked gap in the jottings becomes a stated gap in the notes. An unmarked gap becomes invented detail during expansion.
- Keep reflection out of the jottings page where the setting allows it, or mark it on the spot with a bracketed tag such as [my read]. A reaction written into the jottings without a mark will be expanded into the Description section as if it had been observed.
- Keep description separate from reflection and inference.
- Description holds what a camera and a microphone in the room would have registered: actions, positions, movements, counts, sequence, and spoken words reported as speech, for example: at 09:10, two people entered and sat at table 4.
- Reflection holds everything else: what the observer thinks was meant, felt, or intended, why something might have happened, patterns the observer thinks are forming, emotional reactions of the observer, and questions to follow up. Reflection is valuable data about the observer's reading of the setting. It is not a record of the setting, and it lives only in the Reflection section.
- Apply the test line by line during expansion: if the sentence states a motive, a feeling, or an intention as a fact about another person, it is inference, no matter how confident it feels. Motives and feelings can be written in Description only as observed signs, stated as signs: what the person did and said, with the reading of it placed in Reflection.
- Watch for compact inference wording that smuggles a reading into a description line: words such as obviously, deliberately, and on purpose, and phrases such as seemed angry or clearly felt. The checker flags a documented list of these markers in Description lines. A flagged line is rewritten in one of two ways: state the observed signs in Description, or move the reading to Reflection.
- Do not delete inference. Move it. An inference recorded in Reflection, dated to the session, can be tested against later sessions. An inference deleted is lost, and an inference left in Description is a defect.
- Expand the jottings into full notes the same day.
- Expand on the same calendar day as the observation, while sequence, wording, and detail are still recoverable from memory plus jottings. Set the Note-Date header to the true date the expanded notes are written. The checker measures expansion lag as Note-Date minus Date in days, and any lag above 0 breaks the same-day rule.
- Write the expansion in the format from step 2: header first, then Description as full sentences in time order, then Verbatim lines each wrapped in double quotes, then Reflection. Expand every jotting or account for it. A jotting that is dropped is dropped for a stated reason, for example illegible or about an out-of-scope moment, and the reason is noted in the session log.
- Fill in connective detail from memory only where the jottings support it: order, setting detail, who was present. Where memory and jottings disagree, the jottings win, because they were written in the moment.
- Never backdate an expansion. If expansion slips to a later day, write the true Note-Date, let the checker flag the lag, and state the lag in the session record. A late expansion honestly dated can still be used with care. A backdated one hides a quality problem every later reader needs to know about.
- Mark later recall as later recall. Anything remembered and added after the day of observation is added as a line starting with the prefix [later recall], followed by the date it was added, and it goes in the Reflection section or in a dated addition at the end of the entry. Later recall is never merged silently into Description lines written on the day.
- Apply privacy basics to the notes themselves.
- Write labels, not names, as the default from step 2: pseudonyms or role labels for observed people, and no direct identifiers such as full names, addresses, phone numbers, account names, or exact job titles for private individuals, unless the research purpose needs one and the basis from step 1 covers it.
- Leave out identifying detail that the focus question does not need. A note can be complete for research purposes and still omit where a person lives, what they look like beyond what the activity requires, and details about people who were only passing through the setting.
- Take extra care in sensitive settings and with minors: settings involving health, money trouble, discipline, or private family matters, and any setting where children are present, call for stricter defaults. Fewer details, labels only, no verbatim lines from minors unless the basis in force plainly covers them, and no notes at all in parts of the setting where people expect privacy. When in doubt, record less and note the gap.
- Store notes securely from the moment they exist: jottings and expanded notes go in the project storage, not in personal accounts or loose files, and the label-to-person link file, if one exists, is stored separately from the notes. Who can read the notes is set by the project and any ethics approval in force. This skill does not state a specific storage standard or retention period, because those vary and were not verified here.
- Handle quotations with the same care as names. An exact quote can identify a speaker inside a small setting even with a label attached. Before notes are shared beyond the project, read verbatim lines again and cut or paraphrase any quote that points at a person who did not agree to be quoted.
- Review the expanded notes against the jottings.
- Read the expanded entry once against the jottings, line by line: every Description line traces to a jotting or to same-day memory noted during expansion, every Verbatim line was marked as a quote in the jottings, and no Reflection content has landed in Description.
- Check the header against the session: Date, Start, and End match the session as it happened, Setting names the place at the level of detail the project uses, Observer is filled in, and Note-Date is the true expansion date.
- Check sequence: events in Description run in time order and timestamps do not run backwards. Out-of-order notes usually mean two jotting pages were expanded in the wrong order, and the fix is to reorder, not to rewrite content.
- Note what the session did not cover: parts of the setting never watched, roles never observed, and times with no jottings. Write this as a coverage note in the session log. Coverage gaps shape what later sessions need to watch for, and they limit what this session's notes can support.
- Run the checker and fix what it flags.
- Run notes_check.py from the Operating Rules section on the expanded notes files for the session. Read every figure it prints: entries found, entries missing a required header field, description lines with a flagged inference marker, verbatim lines not wrapped in quotes, and late expansions.
- Fix faults in the notes, in this order. Fill in missing header fields from the jottings and the session log, or state in the session log why a field cannot be recovered. Rewrite flagged description lines under the rule in step 4. Move verbatim lines that were not captured exactly out of the Verbatim section. Record late expansions in the session record with their lag.
- Do not edit the jottings to make the checker output look better. Jottings are the raw record. Fixes go in the expanded notes and in the log, where a later reader can see what changed.
- Rerun the checker after fixes and save the final output with the session record. The saved output, not a memory of running the checker, is the evidence that the closing check happened.
- File the notes and close the session.
- File the jottings, the expanded notes, the checker output, and the session log entry together under the session date. A reader opening the session file should be able to move from log to notes to jottings without hunting across folders.
- Write the session log entry the same day: focus question, session date and times, setting, the basis the session ran under from step 1, coverage gaps from step 7, faults the checker flagged and how each was handled, and any late expansion with its lag.
- Carry open questions forward in writing: what the next session should watch for, which inferences in Reflection need testing against new observation, and any consent or access point to settle before returning. Open questions held only in memory are lost between sessions.
- Stop at a complete session record. Analysis across sessions, coding of the notes, and any write-up of findings are separate work that starts from these records. They do not change the notes.
Output Contract
Deliver a field notes record for each observation session, with these parts, in this order:
- Session log entry: the focus question, the session date, start and end times, the setting, the basis the session ran under (Workflow step 1), coverage gaps, faults flagged by the checker and how each was handled, and any late expansion with its lag in days.
- Expanded notes: one entry per session in the format defined in Workflow step 2, with a complete header (Date, Start, End, Setting, Observer, Note-Date), and Description, Verbatim, and Reflection sections. Verbatim lines are wrapped in double quotes. Later recall appears only as lines starting with [later recall] and carrying the date they were added.
- Jottings record: the jottings as taken, unedited after expansion, filed with the session. Any jotting not expanded is listed in the session log with the reason.
- Checker record: the full output of notes_check.py on the expanded notes files, saved after the final fix pass. On the worked fixture in the Operating Rules section the totals are: files 2, entries 4, entries missing a required header field 2, description lines with a flagged inference marker 3, verbatim lines not wrapped in quotes 2, and late expansions 1. The clean fixture file holds 2 entries with 0 faults of every kind. The mixed fixture file holds 2 entries, both missing a header field (entry 1 missing Setting, entry 2 missing End), with 3 flagged description lines, 2 unquoted verbatim lines, and 1 late expansion at a lag of 2 days (Date 2026-10-11, Note-Date 2026-10-13).
- Privacy record: the naming rule used (pseudonyms or role labels), where the label-to-person link file is stored if one exists, any identifying detail deliberately omitted, and any verbatim lines cut or paraphrased before the notes were shared beyond the project.
Operating Rules
- Jottings stay raw. Jottings are never edited after expansion begins. Corrections, additions, and second thoughts go in the expanded notes, in the Reflection section, or in a [later recall] line with its date, so the in-the-moment record stays intact.
- Same-day expansion, honestly dated. Expanded notes are written on the calendar day of the observation. Note-Date always holds the true date the expansion was written. A late expansion is reported with its lag, never hidden by backdating.
- Description holds observed signs only. Actions, counts, positions, sequence, and reported speech go in Description. Motives, feelings, and intentions stated as facts about another person go in Reflection. A description line flagged by the checker is rewritten to state the signs, or the reading is moved to Reflection.
- Verbatim means exact. A line sits in the Verbatim section, wrapped in double quotes, only if the words were captured exactly in the jottings and marked as a quote there. A paraphrase never becomes a quote during expansion, however confident the memory feels.
- Labels by default. Observed people are recorded under pseudonyms or role labels. Real names and other direct identifiers appear only when the research purpose needs them and the consent basis in force covers them. The link between labels and people is stored separately from the notes.
- Setting rules and consent basis come first. If the rules of the setting, an opt-out by an observed person, or the ethics approval in force conflict with complete notes, the notes give way. Record the gap and the reason. Do not record first and settle permission later.
- Numbers come from the checker output. Counts of entries, missing headers, flagged lines, unquoted lines, and late expansions are quoted from notes_check.py output, never from memory of reading the notes. If a needed count is not in the output, extend the script and rerun it rather than estimating.
- Later recall is labeled, never merged. Material remembered after the day of observation enters the notes only as a [later recall] line with the date it was added, placed outside the Description lines written on the day.
- Use the checker below for the closing completeness check. Save it as notes_check.py, run it on the fixture to confirm your copy works, then run it on real note files by passing the file paths as arguments. Report numbers from its output, not from memory of the entries.
Field notes checker (notes_check.py)
Run: python3 notes_check.py prints the check for the built-in fixture. Run: python3 notes_check.py --self-test prints the same check, asserts the fixture totals, confirms that the clean fixture file has no faults, and ends with self_test: PASS (fixture totals match, clean file has no faults). Run: python3 notes_check.py my_notes.md checks a real notes file in the same format.
The exact inference marker list the checker searches for in Description lines, matched case-insensitively as substrings, is the INFERENCE_MARKERS list in the code: obviously, clearly felt, seemed angry, seemed bored, seemed nervous, must have felt, deliberately, on purpose.
Expected output for the fixture run:
text
file: clean_notes.md
entries: 2
entries_missing_header: 0
inference_flagged_lines: 0
verbatim_unquoted_lines: 0
late_expansions: 0
file: mixed_notes.md
entries: 2
entries_missing_header: 2
missing_detail: entry 1 missing Setting
missing_detail: entry 2 missing End
inference_flagged_lines: 3
verbatim_unquoted_lines: 2
late_expansions: 1
late_detail: entry 1 lag 2 days (Date 2026-10-11, Note-Date 2026-10-13)
totals:
files: 2
entries: 4
entries_missing_header: 2
inference_flagged_lines: 3
verbatim_unquoted_lines: 2
late_expansions: 1
The fixture is a teaching example with 2 files and 4 entries, built so every fault the checker reports has a case. The clean file holds 2 entries from one day at a community library, each with a complete header, description lines with no flagged markers, verbatim lines all wrapped in quotes, and Note-Date equal to Date. The mixed file holds 2 entries with planted faults: entry 1 is missing the Setting header field, has 2 flagged description lines (one with obviously, one with seemed angry), 1 verbatim line without quotes, and a lag of 2 days between Date 2026-10-11 and Note-Date 2026-10-13. Entry 2 is missing the End header field, has 1 flagged description line (deliberately), and 1 verbatim line without quotes, expanded the same day. The totals across both files are entries 4, entries missing a required header field 2, flagged description lines 3, unquoted verbatim lines 2, and late expansions 1.
notes_check.py (Python 3, standard library only). Save this code as notes_check.py:
python
#!/usr/bin/env python3
"""Check expanded field notes for completeness and separation faults.
Uses only the Python standard library. With no file arguments it checks
the built-in fixture below. With file arguments it checks those files,
in the order given.
Note format (plain text or Markdown, one entry after another):
Each entry starts with a line containing only: ## Entry
Header lines follow, one per line, in the form Field: value
Date: YYYY-MM-DD (the observation date)
Start: HH:MM
End: HH:MM
Setting: free text
Observer: initials or role label
Note-Date: YYYY-MM-DD (the date the expanded notes were written)
Three sections follow, each opened by a heading line:
### Description
### Verbatim
### Reflection
Description lines are plain sentences about what was seen or heard.
Verbatim lines must be wrapped in double quotes: the stripped line
starts with a double quote and ends with a double quote.
Reflection lines are unrestricted.
What it reports, per file and in totals: entries found, entries missing
any required header field (with the missing fields named), description
lines containing a flagged inference marker, verbatim lines not wrapped
in quotes, and entries whose expansion lag (Note-Date minus Date, in
days) is greater than 0, which breaks the same-day rule.
Run:
python3 notes_check.py
python3 notes_check.py --self-test
python3 notes_check.py my_notes.md other_notes.md
"""
import sys
from datetime import date
REQUIRED_FIELDS = ["Date", "Start", "End", "Setting", "Observer", "Note-Date"]
INFERENCE_MARKERS = [
"obviously",
"clearly felt",
"seemed angry",
"seemed bored",
"seemed nervous",
"must have felt",
"deliberately",
"on purpose",
]
SECTION_NAMES = ["Description", "Verbatim", "Reflection"]
FIXTURE_FILES = {
"clean_notes.md": """## Entry
Date: 2026-10-10
Start: 09:00
End: 10:15
Setting: Community library, main reading room
Observer: JR
Note-Date: 2026-10-10
### Description
09:02 Person at table 2 opened a laptop and typed.
09:10 Two people entered, sat at table 4, and placed books on the table.
09:22 Librarian shelved 6 books on the north shelf.
### Verbatim
"Please keep voices low near the desks."
"This copy is due back on Friday."
### Reflection
I wondered whether the room gets busier after 10:00. A separate session would be needed to check.
## Entry
Date: 2026-10-10
Start: 11:00
End: 12:00
Setting: Community library, entrance area
Observer: JR
Note-Date: 2026-10-10
### Description
11:03 Four people waited in line at the returns desk.
11:15 Person at the desk scanned 3 items and handed over a receipt.
### Verbatim
"Do you have the card with you?"
### Reflection
The entrance line moved in bursts. I should time the gaps in the next session.
""",
"mixed_notes.md": """## Entry
Date: 2026-10-11
Start: 14:00
End: 15:00
Observer: JR
Note-Date: 2026-10-13
### Description
14:05 The group was obviously ready to leave early.
14:12 One person seemed angry and tapped the table twice.
14:20 Three people stood and walked to the door.
### Verbatim
"We will finish this part first."
We need more time on this.
### Reflection
The session felt rushed near the end. I should check the schedule next time.
## Entry
Date: 2026-10-12
Start: 10:00
Setting: School hall, morning assembly seating area
Observer: JR
Note-Date: 2026-10-12
### Description
10:04 A speaker read two announcements from a sheet.
10:11 The speaker deliberately skipped the second page.
### Verbatim
Please sit in the marked rows.
"Thank you, we start in five minutes."
### Reflection
The second announcement was not read aloud. The reason was not stated in the room.
""",
}
def split_entries(text):
chunks = []
current = None
for line in text.splitlines():
if line.strip() == "## Entry":
if current is not None:
chunks.append(current)
current = [line]
elif current is not None:
current.append(line)
if current is not None:
chunks.append(current)
return ["\n".join(c) for c in chunks]
def parse_entry(chunk):
headers = {}
sections = {name: [] for name in SECTION_NAMES}
current_section = None
for line in chunk.splitlines():
stripped = line.strip()
if stripped.startswith("### "):
name = stripped[4:].strip()
current_section = name if name in sections else None
continue
if current_section is not None:
if stripped:
sections[current_section].append(line)
continue
for field in REQUIRED_FIELDS:
prefix = field + ":"
if stripped.startswith(prefix):
headers[field] = stripped[len(prefix):].strip()
break
return headers, sections
def check_text(text):
entries = split_entries(text)
missing_header_entries = 0
missing_detail = []
inference_flagged = 0
verbatim_unquoted = 0
late_entries = 0
late_detail = []
for idx, chunk in enumerate(entries, start=1):
headers, sections = parse_entry(chunk)
missing = [f for f in REQUIRED_FIELDS if not headers.get(f)]
if missing:
missing_header_entries += 1
missing_detail.append(f"entry {idx} missing {', '.join(missing)}")
for line in sections["Description"]:
low = line.lower()
if any(marker in low for marker in INFERENCE_MARKERS):
inference_flagged += 1
for line in sections["Verbatim"]:
s = line.strip()
if not (len(s) >= 2 and s.startswith('"') and s.endswith('"')):
verbatim_unquoted += 1
raw_date = headers.get("Date", "")
raw_note = headers.get("Note-Date", "")
try:
lag = (date.fromisoformat(raw_note) - date.fromisoformat(raw_date)).days
except ValueError:
lag = None
if lag is not None and lag > 0:
late_entries += 1
late_detail.append(
f"entry {idx} lag {lag} days (Date {raw_date}, Note-Date {raw_note})"
)
return {
"entries": len(entries),
"entries_missing_header": missing_header_entries,
"missing_detail": missing_detail,
"inference_flagged_lines": inference_flagged,
"verbatim_unquoted_lines": verbatim_unquoted,
"late_expansions": late_entries,
"late_detail": late_detail,
}
def report(files):
totals = {
"entries": 0,
"entries_missing_header": 0,
"inference_flagged_lines": 0,
"verbatim_unquoted_lines": 0,
"late_expansions": 0,
}
for name, text in files:
r = check_text(text)
print(f"file: {name}")
print(f" entries: {r['entries']}")
print(f" entries_missing_header: {r['entries_missing_header']}")
for detail in r["missing_detail"]:
print(f" missing_detail: {detail}")
print(f" inference_flagged_lines: {r['inference_flagged_lines']}")
print(f" verbatim_unquoted_lines: {r['verbatim_unquoted_lines']}")
print(f" late_expansions: {r['late_expansions']}")
for detail in r["late_detail"]:
print(f" late_detail: {detail}")
for key in totals:
totals[key] += r[key]
print("totals:")
print(f" files: {len(files)}")
print(f" entries: {totals['entries']}")
print(f" entries_missing_header: {totals['entries_missing_header']}")
print(f" inference_flagged_lines: {totals['inference_flagged_lines']}")
print(f" verbatim_unquoted_lines: {totals['verbatim_unquoted_lines']}")
print(f" late_expansions: {totals['late_expansions']}")
return totals
def self_test():
totals = report(list(FIXTURE_FILES.items()))
assert totals["entries"] == 4, totals
assert totals["entries_missing_header"] == 2, totals
assert totals["inference_flagged_lines"] == 3, totals
assert totals["verbatim_unquoted_lines"] == 2, totals
assert totals["late_expansions"] == 1, totals
clean = check_text(FIXTURE_FILES["clean_notes.md"])
assert clean["entries"] == 2, clean
assert clean["entries_missing_header"] == 0, clean
assert clean["inference_flagged_lines"] == 0, clean
assert clean["verbatim_unquoted_lines"] == 0, clean
assert clean["late_expansions"] == 0, clean
print("self_test: PASS (fixture totals match, clean file has no faults)")
return 0
def main():
args = sys.argv[1:]
if "--self-test" in args:
return self_test()
paths = [a for a in args if not a.startswith("--")]
if paths:
files = []
for path in paths:
with open(path, encoding="utf-8") as fh:
files.append((path, fh.read()))
report(files)
return 0
report(list(FIXTURE_FILES.items()))
return 0
if __name__ == "__main__":
raise SystemExit(main())
No ratings yet — be the first to rate it.