oc_chat
Loading...
Searching...
No Matches
plan_status.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# oc_chat/scripts/plan_status.py
4
5# OCT-LINT: disable=tests_exist reason="Wiring shim; covered by oc_chat/tests/registry/test_shim_plan_status.py, test_231_worker_report_helper.py and test_blocked_lane_event.py"
6"""
7``.PLAN_STATUS.md`` CLI — moved to :mod:`oc_orchestrator.plan_status`.
8
9Purpose
10-------
11Plan 270 P4. The lifecycle helper and its CLI now live in the standalone
12``oc_orchestrator`` package. This file keeps ``oc_chat.scripts.plan_status``
13working — the path the launch brief, ``dispatch.ps1``, ``registry/migrate``
14and every worker's STEP-0 command have always named — and supplies the two
15defaults that are oc_chat's and not the package's:
16
17- **the program name.** ``--help`` must print exactly what it printed
18 before the split, and ``prog`` is the only line in it that could differ.
19- **the observers.** The package announces lifecycle events and registers
20 no listener; oc_chat mirrors every one of them into the orchestration
21 registry, so this is where :class:`RegistryMirrorObserver` is registered.
22
23Unlike the eight ``core/`` shims this module is NOT a rebinding, because
24it has behaviour of its own: those two defaults. Every other name is
25delegated by :func:`__getattr__`, so ``plan_status.read``,
26``plan_status.Status`` and ``plan_status._split_frontmatter`` all resolve
27to the moved module's own objects.
28
29Responsibilities
30----------------
31- :func:`main` — the package's CLI with oc_chat's ``prog`` and observers.
32- :func:`__getattr__` — every other name, delegated unchanged.
33
34Diagnostics
35-----------
36Domain: OC_CHAT.MAIN
37Levels:
38 L2 - lifecycle events (a command was run through this path)
39 L3 - semantic details
40 L4 - deep tracing (delegated name lookups)
41
42Contracts
43---------
44- Output is byte-identical to the pre-270 module for every sub-command,
45 and so are the registry rows each one writes. That is the whole point:
46 the split is invisible from here.
47- The observer import is deferred into :func:`main` exactly as the
48 pre-270 ``_resolve_observers`` deferred it, so importing this module
49 costs no registry machinery.
50- Retirement rule (plan 270 P8): this path stays until an explicit
51 retirement plan retargets the brief, ``dispatch.ps1`` and the workflow
52 doc. New code names ``oc_orchestrator.plan_status`` directly.
53
54Dependencies
55------------
56- oc_diagnostics (structured debug logging via _dbg)
57- oc_orchestrator.plan_status (the moved module this path wraps)
58- oc_chat.registry.mirror_observer (lazy; RegistryMirrorObserver, the observer this path registers)
59"""
60
61from __future__ import annotations
62
63import sys
64from typing import Any
65
66from oc_diagnostics import _dbg
67
68from oc_orchestrator import plan_status as _moved
69
70#: The program name this path has always printed in ``--help``.
71PROG = "python -m oc_chat.scripts.plan_status"
72
73_dbg("OC_CHAT.MAIN", "module", "plan_status shim -> oc_orchestrator.plan_status", 4)
74
75
76def __getattr__(name: str) -> Any:
77 """Delegate every name this shim does not define to the moved module.
78
79 PEP 562 module ``__getattr__``. It covers the private names two
80 oc_chat callers reach — ``registry/migrate.py`` wants
81 ``_split_frontmatter`` — as well as every public one, so no importer
82 had to change when the code moved.
83 """
84 return getattr(_moved, name)
85
86
87def main(argv: list[str] | None = None) -> int:
88 """Run one sub-command with oc_chat's program name and observers."""
89 func = "plan_status.main"
90 from oc_chat.registry.mirror_observer import RegistryMirrorObserver
91
92 _dbg("OC_CHAT.MAIN", func, "running with the registry mirror registered", 3)
93 return _moved.main(argv, prog=PROG, observers=(RegistryMirrorObserver(),))
94
95
96if __name__ == "__main__":
97 sys.exit(main())