oc_chat
Loading...
Searching...
No Matches
oc_chat.registry.source.scanner Namespace Reference

Classes

class  ScannedRecord

Functions

bool _is_noise (str name)
list[Path] _walk_files (Path root, frozenset[str] temp_dir_names)
ScannedRecord _classify (Path root, Path path, frozenset[str] phase_stems)
None _check_casefold_stems (Path root, list[Path] files)
list[Path] observed_files (Path root, *, frozenset[str] temp_dir_names=frozenset())
list[ScannedRecord] scan_source_tree (Path root, *, frozenset[str] temp_dir_names=frozenset())

Variables

frozenset NOISE_EXACT = frozenset({".DS_Store", "Thumbs.db"})
tuple NOISE_GLOBS = ("*.swp", "*~", "*.tmp")
frozenset ITEM_TRACK_KINDS
frozenset CHANGELOG_KINDS = frozenset({"roadmap", "product"})
str _CASEFOLD_EXCLUDE = "README.md"

Detailed Description

Closed-world scanner for the AuthoredSource tree.

Purpose
-------
Enumerate ``oc_chat/roadmap/source/**`` and classify every file against the
Registry Source & Storage Spec V0.22 §3.1 allowlist, hard-failing any unknown
path and enforcing the ``phases/`` path-shape rule, while silently skipping a
hardcoded OS/editor-noise set independent of ``.gitignore``.

Responsibilities
----------------
- Walk the tree fail-closed (``SourceScanError`` on unreadable trees).
- Classify each recognised file into a typed ``ScannedRecord`` (entity kind +
  resolution metadata: ``track_kind``, promoted ``phase_code``, changelog kind).
- Enforce the two legal ``phases/`` shapes (depth-1 phase, depth-2 promoted
  item under an existing ``phases/<code>.md``); reject every other shape.
- Skip ``.DS_Store``/``Thumbs.db``/``*.swp``/``*~``/``*.tmp`` silently.

Diagnostics
-----------
Domain: OC_CHAT.MAIN
Levels:
    L2 - scan lifecycle
    L3 - per-file classification
    L4 - phases path-shape resolution

Contracts
---------
- Read-only: never mutates the source tree.
- Output is deterministic — records sorted by POSIX relative path.
- Unknown/illegal paths raise ``SourceValidationError`` with the offending path;
  unreadable trees raise ``SourceScanError`` (``raw_source_tree_hash`` → null).

Dependencies
------------
- oc_diagnostics (structured debug logging via _dbg)
- oc_chat.registry.source.errors (SRC_* codes + exception types)

Function Documentation

◆ _check_casefold_stems()

None oc_chat.registry.source.scanner._check_casefold_stems ( Path root,
list[Path] files )
protected
Plan 142j R7 (VC-0007, layer 1): reject a **per-directory** casefold stem
collision over every discovered file BEFORE loading records (§3.2).

``canonical.load_record`` is per-file and cannot see cross-file collisions;
only the scanner walks directories, so the physical stem-vs-stem check is
owned here. A case-only-different pair (e.g. ``Foo.md``/``foo.md`` in one dir)
breaks every case-insensitive NTFS/APFS checkout ⇒ ``SRC_DUP_OR_STEM_MISMATCH``.
The literal ``README.md`` is excluded (not an entity record).

Definition at line 208 of file scanner.py.

Here is the caller graph for this function:

◆ _classify()

ScannedRecord oc_chat.registry.source.scanner._classify ( Path root,
Path path,
frozenset[str] phase_stems )
protected
Classify one file against the §3.1 allowlist + ``phases/`` path-shape rule.

Definition at line 128 of file scanner.py.

Here is the caller graph for this function:

◆ _is_noise()

bool oc_chat.registry.source.scanner._is_noise ( str name)
protected
True if ``name`` is in the hardcoded OS/editor-noise set (§3.1).

Definition at line 92 of file scanner.py.

Here is the caller graph for this function:

◆ _walk_files()

list[Path] oc_chat.registry.source.scanner._walk_files ( Path root,
frozenset[str] temp_dir_names )
protected
Return all non-noise files under ``root`` (fail-closed on read errors).

Definition at line 99 of file scanner.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ observed_files()

list[Path] oc_chat.registry.source.scanner.observed_files ( Path root,
* ,
frozenset[str] temp_dir_names = frozenset() )
All physically-observed non-noise files under ``root`` (sorted).

Used by the raw-source-tree-hash preimage (§10), which includes files that
later fail closed-world validation — so it walks independently of
classification and is computable before any parse.

Definition at line 238 of file scanner.py.

Here is the call graph for this function:

◆ scan_source_tree()

list[ScannedRecord] oc_chat.registry.source.scanner.scan_source_tree ( Path root,
* ,
frozenset[str] temp_dir_names = frozenset() )
Scan ``root`` and return the classified records (sorted by POSIX path).

Raises ``SourceScanError`` if the tree cannot be enumerated, or
``SourceValidationError`` (``SRC_UNKNOWN_FILE`` / ``SRC_BAD_PHASE_PATH``) on
the first offending path in sorted order.

Definition at line 254 of file scanner.py.

Here is the call graph for this function:

Variable Documentation

◆ _CASEFOLD_EXCLUDE

str oc_chat.registry.source.scanner._CASEFOLD_EXCLUDE = "README.md"
protected

Definition at line 205 of file scanner.py.

◆ CHANGELOG_KINDS

frozenset oc_chat.registry.source.scanner.CHANGELOG_KINDS = frozenset({"roadmap", "product"})

Definition at line 75 of file scanner.py.

◆ ITEM_TRACK_KINDS

frozenset oc_chat.registry.source.scanner.ITEM_TRACK_KINDS
Initial value:
1= frozenset(
2 {"backlog", "vision", "git_workflow", "pre_m0_era"}
3)

Definition at line 71 of file scanner.py.

◆ NOISE_EXACT

frozenset oc_chat.registry.source.scanner.NOISE_EXACT = frozenset({".DS_Store", "Thumbs.db"})

Definition at line 67 of file scanner.py.

◆ NOISE_GLOBS

tuple oc_chat.registry.source.scanner.NOISE_GLOBS = ("*.swp", "*~", "*.tmp")

Definition at line 68 of file scanner.py.