throughline-ratify 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- throughline_ratify/__init__.py +14 -0
- throughline_ratify/cli.py +94 -0
- throughline_ratify/core.py +698 -0
- throughline_ratify/tui.py +693 -0
- throughline_ratify-0.1.2.dist-info/METADATA +135 -0
- throughline_ratify-0.1.2.dist-info/RECORD +11 -0
- throughline_ratify-0.1.2.dist-info/WHEEL +5 -0
- throughline_ratify-0.1.2.dist-info/entry_points.txt +3 -0
- throughline_ratify-0.1.2.dist-info/licenses/LICENSE +201 -0
- throughline_ratify-0.1.2.dist-info/licenses/NOTICE +11 -0
- throughline_ratify-0.1.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Copyright (c) 2026 Henry J Grech-Cini
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
"""throughline-ratify — a full-screen terminal companion for
|
|
4
|
+
working through the throughline items that await human ratification."""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from importlib.metadata import PackageNotFoundError, version as _version
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
__version__ = _version("throughline-ratify")
|
|
11
|
+
except PackageNotFoundError: # running from a source tree
|
|
12
|
+
__version__ = "0.0.0+unknown"
|
|
13
|
+
|
|
14
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Copyright (c) 2026 Henry J Grech-Cini
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
"""``tl-ratify`` — the entry point.
|
|
4
|
+
|
|
5
|
+
Launches the full-screen ratification cockpit over the throughline project
|
|
6
|
+
enclosing ``--path`` (default: the current directory). ``--list`` prints the same
|
|
7
|
+
worklist to stdout without curses, for pipelines, CI logs and quick glances.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import sys
|
|
13
|
+
from importlib.metadata import PackageNotFoundError, version as _pkg_version
|
|
14
|
+
|
|
15
|
+
from . import core
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _v(name: str) -> str:
|
|
19
|
+
try:
|
|
20
|
+
return _pkg_version(name)
|
|
21
|
+
except PackageNotFoundError: # pragma: no cover - source tree
|
|
22
|
+
return "0.0.0+unknown"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _version_string() -> str:
|
|
26
|
+
return (
|
|
27
|
+
f"tl-ratify {_v('throughline-ratify')} "
|
|
28
|
+
f"(throughline-compose {_v('throughline-compose')}, throughline {_v('throughline')})"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
33
|
+
p = argparse.ArgumentParser(
|
|
34
|
+
prog="tl-ratify",
|
|
35
|
+
description="A full-screen assistant for ratifying throughline items (compose-aware).",
|
|
36
|
+
)
|
|
37
|
+
p.add_argument("--version", action="version", version=_version_string())
|
|
38
|
+
p.add_argument("-C", "--path", default=".", help="project root or a path within it (default: .)")
|
|
39
|
+
p.add_argument("--by", default=None,
|
|
40
|
+
help="the ratifier recorded on sign-off (default: the current user)")
|
|
41
|
+
p.add_argument("--list", action="store_true",
|
|
42
|
+
help="print the ratification worklist and exit (no TUI)")
|
|
43
|
+
p.add_argument("--all", action="store_true",
|
|
44
|
+
help="with --list, include already-ratified items")
|
|
45
|
+
p.add_argument("--sort", choices=core.SORTS, default="concern",
|
|
46
|
+
help="worklist ordering: concern (default), roots (shallowest "
|
|
47
|
+
"grounding depth first) or leaves (deepest first)")
|
|
48
|
+
return p
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _print_list(session: core.Session, show_all: bool, sort: str) -> int:
|
|
52
|
+
rows = core.build_queue(session, show_all=show_all, sort=sort)
|
|
53
|
+
scope = "composed union" if session.composed else "local graph"
|
|
54
|
+
done, total = core.ratification_progress(session)
|
|
55
|
+
print(f"{session.project_name} \u2014 {scope} \u2502 {done}/{total} ratified")
|
|
56
|
+
if session.composed:
|
|
57
|
+
for s in session.sources:
|
|
58
|
+
print(f" source {s.namespace}: {s.location}")
|
|
59
|
+
if not rows:
|
|
60
|
+
print("nothing to ratify \u2014 all clear")
|
|
61
|
+
return 0
|
|
62
|
+
header = "item(s) shown" if show_all else "item(s) pending ratification"
|
|
63
|
+
print(f"{len(rows)} {header} (sort: {sort}):\n")
|
|
64
|
+
for r in rows:
|
|
65
|
+
mark = "ratify-ready" if r.ratifiable_now else r.concern
|
|
66
|
+
print(f" {r.icon} {r.uid:<14} [{r.status:<10}] {mark:<12} {r.title}")
|
|
67
|
+
return 0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main(argv: list[str] | None = None) -> int:
|
|
71
|
+
args = build_parser().parse_args(argv)
|
|
72
|
+
try:
|
|
73
|
+
session = core.open_session(args.path)
|
|
74
|
+
except core.RatifierError as exc:
|
|
75
|
+
print(f"tl-ratify: {exc}", file=sys.stderr)
|
|
76
|
+
return 2
|
|
77
|
+
|
|
78
|
+
if args.list:
|
|
79
|
+
return _print_list(session, args.all, args.sort)
|
|
80
|
+
|
|
81
|
+
if not sys.stdout.isatty():
|
|
82
|
+
print("tl-ratify: not a terminal; use --list for non-interactive output",
|
|
83
|
+
file=sys.stderr)
|
|
84
|
+
return 2
|
|
85
|
+
|
|
86
|
+
from . import tui # deferred: only import curses when we actually open the UI
|
|
87
|
+
|
|
88
|
+
ratifier = args.by or core.default_ratifier()
|
|
89
|
+
tui.run(session, ratifier)
|
|
90
|
+
return 0
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__": # pragma: no cover
|
|
94
|
+
raise SystemExit(main())
|