-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtm
More file actions
executable file
·166 lines (128 loc) · 4.64 KB
/
tm
File metadata and controls
executable file
·166 lines (128 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/env python3
"""Task Orchestrator CLI entrypoint (thin bootstrap + command dispatch)."""
from __future__ import annotations
import logging
import subprocess
import sys
from pathlib import Path
LOGGER = logging.getLogger("task_orchestrator.tm")
# Add src directory to path
SCRIPT_DIR = Path(__file__).parent
SRC_DIR = SCRIPT_DIR / "src"
if SRC_DIR.exists():
sys.path.insert(0, str(SRC_DIR))
from cli.context import CLIContext
from cli.dispatcher import CommandDispatcher
from cli.handlers.admin import ADMIN_COMMANDS, handle_admin
from cli.handlers.collab import COLLAB_COMMANDS, handle_collab
from cli.handlers.core import CORE_COMMANDS, handle_core
from cli.handlers.enforcement import handle_enforcement
from storage_paths import resolve_db_path, resolve_storage_root
def update_orchestrator_md(tm: object) -> None:
"""Update ORCHESTRATOR.md after task lifecycle changes."""
try:
from orchestrator_discovery import OrchestratorDiscovery
discovery = OrchestratorDiscovery(tm)
discovery.update_orchestrator_md()
except Exception as e:
print(f"Warning: Failed to update ORCHESTRATOR.md: {e}", file=sys.stderr)
def parse_agent_id(argv: list[str]) -> tuple[list[str], str | None]:
"""Parse and strip --agent-id from argv."""
args = list(argv)
agent_id_override = None
if "--agent-id" in args:
idx = args.index("--agent-id")
if idx + 1 >= len(args):
print("Error: --agent-id requires a value")
raise SystemExit(1)
agent_id_override = args[idx + 1]
del args[idx : idx + 2]
return args, agent_id_override
def build_enforcement_engine() -> object | None:
"""Initialize optional enforcement engine."""
try:
from enforcement import EnforcementEngine
db_dir = resolve_storage_root()
db_dir.mkdir(parents=True, exist_ok=True)
return EnforcementEngine(resolve_db_path())
except ImportError:
LOGGER.debug("Enforcement module unavailable; continuing without enforcement engine")
return None
def build_dispatcher() -> CommandDispatcher:
"""Build command registry."""
dispatcher = CommandDispatcher()
dispatcher.register(CORE_COMMANDS, handle_core)
dispatcher.register(COLLAB_COMMANDS, handle_collab)
dispatcher.register(ADMIN_COMMANDS, handle_admin)
return dispatcher
def print_help() -> None:
print(
"""Task Manager - Modular CLI
Core:
init | add | list | show | update | complete | delete | assign | export | watch
Collaboration:
join | share | note | discover | sync | context | progress | feedback
Admin:
migrate | config | metrics | critical-path | report | template | wizard | hooks
phase-* | agent-*
Enforcement:
validate-orchestration | fix-orchestration --interactive
config --enforce-usage true|false | --show-enforcement | --enforcement-level
Global Options:
--agent-id <id>
Environment:
TM_DB_PATH
"""
)
def main() -> int:
argv, agent_id_override = parse_agent_id(sys.argv)
if len(argv) < 2:
print("Usage: tm <command> [args]")
print("Commands: init, add, list, show, update, complete, export, etc.")
return 1
command = argv[1]
if command in {"--help", "-h", "help"}:
print_help()
return 0
enforcement_engine = build_enforcement_engine()
enforcement_result = handle_enforcement(command, argv, enforcement_engine)
if enforcement_result is not None:
return enforcement_result
if enforcement_engine and command in {
"add",
"join",
"share",
"note",
"discover",
"sync",
"context",
"assign",
"watch",
"template",
}:
if not enforcement_engine.enforce_orchestration(command):
return 1
try:
from tm_production import TaskManager
tm = TaskManager(agent_id_override=agent_id_override)
except ImportError as e:
print(f"Error importing production module: {e}")
return 1
context = CLIContext(argv=argv, tm=tm, update_orchestrator_md=update_orchestrator_md)
dispatcher = build_dispatcher()
result = dispatcher.dispatch(command, context)
if result is None:
print(f"Command '{command}' not yet implemented in modular CLI")
return 1
return result
def find_repo_root() -> Path:
"""Find git repository root."""
try:
result = subprocess.run(
["git", "rev-parse", "--show-toplevel"], capture_output=True, text=True, check=True
)
return Path(result.stdout.strip())
except subprocess.CalledProcessError:
return Path.cwd()
if __name__ == "__main__":
raise SystemExit(main())