main.py
python
sha256:4671b7f787ddbe63ced31c895b688c77ab495653b65a730b423329f26b3c1439
feat: K1-P1 complete — agent provenance, build-verification…
Sonnet 4.6
patch
58 days ago
| 1 | """Overseer CLI entrypoint and argument parsing (§K4.1).""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | import argparse |
| 6 | import sys |
| 7 | from pathlib import Path |
| 8 | |
| 9 | from cli.args import extract_global_args |
| 10 | |
| 11 | COMMANDS = frozenset({"init", "sync", "status", "review", "governance-sync", "verify-step", "honesty-status", "ledger"}) |
| 12 | from cli.commands.governance_sync import run_governance_sync_command |
| 13 | from cli.commands.honesty_status import run_honesty_status_command |
| 14 | from cli.commands.init import run_init |
| 15 | from cli.commands.ledger import run_ledger_command |
| 16 | from cli.commands.review import run_review |
| 17 | from cli.commands.status import run_status |
| 18 | from cli.commands.sync import run_sync |
| 19 | from cli.commands.verify_step import run_verify_step_command |
| 20 | from cli.context import CliContext |
| 21 | from cli.kit_root import kit_version |
| 22 | from cli.output import OutputContext |
| 23 | |
| 24 | |
| 25 | def build_parser() -> argparse.ArgumentParser: |
| 26 | """Construct the frozen argument parser.""" |
| 27 | parser = argparse.ArgumentParser(prog="overseer", description="Overseer Kit vendoring CLI") |
| 28 | parser.add_argument("--version", action="store_true", help="Print kit version and exit") |
| 29 | parser.add_argument("-C", "--repo", metavar="PATH", help="Repo root") |
| 30 | parser.add_argument("--config", metavar="PATH", help="Config file path") |
| 31 | parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON") |
| 32 | parser.add_argument("-q", "--quiet", action="store_true", help="Suppress non-essential stdout") |
| 33 | parser.add_argument("-v", "--verbose", action="store_true", help="Verbose diagnostics on stderr") |
| 34 | parser.add_argument("--no-color", action="store_true", help="Disable ANSI color") |
| 35 | |
| 36 | subparsers = parser.add_subparsers(dest="command") |
| 37 | |
| 38 | init_parser = subparsers.add_parser("init", help="First install into a repo") |
| 39 | init_parser.add_argument("--regime", choices=["muse+git-mirror", "muse-only", "git-only"]) |
| 40 | init_parser.add_argument("--repo-name", metavar="NAME") |
| 41 | init_parser.add_argument("--docs-dir", metavar="PATH", default="docs") |
| 42 | init_parser.add_argument("--from-config", metavar="PATH") |
| 43 | init_parser.add_argument("--force", action="store_true") |
| 44 | init_parser.add_argument("--non-interactive", action="store_true") |
| 45 | init_parser.add_argument("--dry-run", action="store_true") |
| 46 | init_parser.add_argument( |
| 47 | "--migrate", |
| 48 | action="store_true", |
| 49 | help="Preserve existing living docs; lock origin:preserved (K6)", |
| 50 | ) |
| 51 | init_parser.add_argument( |
| 52 | "--include-preserved", |
| 53 | action="store_true", |
| 54 | help="With --force: promote living docs to origin:kit (pilot-forbidden)", |
| 55 | ) |
| 56 | |
| 57 | sync_parser = subparsers.add_parser("sync", help="Update vendored footprint") |
| 58 | sync_parser.add_argument("--dry-run", action="store_true") |
| 59 | sync_parser.add_argument("--diff", action="store_true", default=None) |
| 60 | sync_parser.add_argument("--no-diff", action="store_false", dest="diff") |
| 61 | sync_parser.add_argument("--only", action="append", metavar="GLOB") |
| 62 | sync_parser.add_argument("--force", action="store_true") |
| 63 | sync_parser.add_argument("-y", "--yes", action="store_true") |
| 64 | sync_parser.add_argument( |
| 65 | "--include-preserved", |
| 66 | action="store_true", |
| 67 | help="With --force: promote living docs to origin:kit (pilot-forbidden)", |
| 68 | ) |
| 69 | |
| 70 | status_parser = subparsers.add_parser("status", help="Read-only status report") |
| 71 | status_parser.add_argument("--exit-code", action="store_true") |
| 72 | status_parser.add_argument("--check-footprint", action="store_true") |
| 73 | |
| 74 | review_parser = subparsers.add_parser("review", help="Freeze-contract review") |
| 75 | review_parser.add_argument("--freeze", required=True, dest="freeze_path", metavar="PATH") |
| 76 | review_parser.add_argument("--dry-run", action="store_true") |
| 77 | review_parser.add_argument("--mode", choices=["agent", "human"]) |
| 78 | review_parser.add_argument("--provider", choices=["local", "api"]) |
| 79 | review_parser.add_argument("--model", metavar="LABEL") |
| 80 | review_parser.add_argument("--no-stamp", action="store_true") |
| 81 | review_parser.add_argument("--checklist", metavar="PATH") |
| 82 | |
| 83 | gs_parser = subparsers.add_parser( |
| 84 | "governance-sync", |
| 85 | help="Governance hygiene agent (default dry-run)", |
| 86 | ) |
| 87 | gs_parser.add_argument( |
| 88 | "--write", |
| 89 | action="store_true", |
| 90 | help="Apply doc patches, commit on feature branch, and push (default is dry-run)", |
| 91 | ) |
| 92 | gs_parser.add_argument( |
| 93 | "--dry-run", |
| 94 | action="store_true", |
| 95 | help="Explicit dry-run (default when --write is absent)", |
| 96 | ) |
| 97 | gs_parser.add_argument( |
| 98 | "--lane", |
| 99 | metavar="NAME", |
| 100 | help="Sync only this configured docs lane (requires docs.lanes in config)", |
| 101 | ) |
| 102 | gs_parser.add_argument( |
| 103 | "--all-lanes", |
| 104 | action="store_true", |
| 105 | help="Sync every configured lane; skip lanes with missing doc files", |
| 106 | ) |
| 107 | |
| 108 | vs_parser = subparsers.add_parser("verify-step", help="L1 checkpoint orchestrator (K9b)") |
| 109 | vs_parser.add_argument("--manifest", metavar="PATH", help="Active manifest path") |
| 110 | vs_parser.add_argument("--step", metavar="ID", help="Verify one step") |
| 111 | vs_parser.add_argument( |
| 112 | "--through", |
| 113 | metavar="TOKEN", |
| 114 | help="Verify through current step (only 'current' accepted)", |
| 115 | ) |
| 116 | vs_parser.add_argument("--all", action="store_true", help="Verify full template order") |
| 117 | vs_parser.add_argument("--policy", metavar="PATH", help="Policy file override") |
| 118 | vs_parser.add_argument( |
| 119 | "--dry-run", |
| 120 | action="store_true", |
| 121 | help="Plan only; no script invoke or manifest writes", |
| 122 | ) |
| 123 | |
| 124 | hs_parser = subparsers.add_parser("honesty-status", help="L2 co-requirement check (K10)") |
| 125 | hs_parser.add_argument("--hook", metavar="HOOK") |
| 126 | hs_parser.add_argument("--artifact", metavar="PATH") |
| 127 | hs_parser.add_argument("--producer-session", metavar="ID") |
| 128 | |
| 129 | ledger_parser = subparsers.add_parser("ledger", help="L2 verdict ledger (K10)") |
| 130 | ledger_sub = ledger_parser.add_subparsers(dest="ledger_action", required=True) |
| 131 | |
| 132 | append_parser = ledger_sub.add_parser("append", help="Append a ledger entry") |
| 133 | append_parser.add_argument("--kind", metavar="KIND", required=True) |
| 134 | append_parser.add_argument("--file", metavar="JSON_PATH") |
| 135 | append_parser.add_argument("--stdin", action="store_true") |
| 136 | |
| 137 | ledger_sub.add_parser("verify", help="Verify ledger hash chain") |
| 138 | |
| 139 | show_parser = ledger_sub.add_parser("show", help="Show recent ledger entries") |
| 140 | show_parser.add_argument("--last", type=int, metavar="N") |
| 141 | |
| 142 | return parser |
| 143 | |
| 144 | |
| 145 | def main(argv: list[str] | None = None, *, ctx: CliContext | None = None) -> int: |
| 146 | """CLI main; return exit code.""" |
| 147 | parser = build_parser() |
| 148 | raw_argv = list(argv) if argv is not None else sys.argv[1:] |
| 149 | global_argv, rest_argv = extract_global_args(raw_argv) |
| 150 | if rest_argv and rest_argv[0] not in COMMANDS: |
| 151 | print(f"unknown command: {rest_argv[0]}", file=sys.stderr) |
| 152 | return 1 |
| 153 | try: |
| 154 | args = parser.parse_args(global_argv + rest_argv) |
| 155 | except SystemExit as exc: |
| 156 | code = exc.code |
| 157 | return 1 if code == 2 else (int(code) if isinstance(code, int) else 1) |
| 158 | |
| 159 | if args.version: |
| 160 | print(kit_version()) |
| 161 | return 0 |
| 162 | |
| 163 | if args.command is None: |
| 164 | parser.print_help() |
| 165 | return 0 |
| 166 | |
| 167 | runtime = ctx or CliContext.create() |
| 168 | if ctx is None: |
| 169 | runtime = CliContext.create( |
| 170 | output=OutputContext( |
| 171 | json_mode=args.json, |
| 172 | quiet=args.quiet, |
| 173 | verbose=args.verbose, |
| 174 | no_color=args.no_color, |
| 175 | ), |
| 176 | cwd=Path.cwd(), |
| 177 | ) |
| 178 | else: |
| 179 | runtime.output.json_mode = args.json or runtime.output.json_mode |
| 180 | runtime.output.quiet = args.quiet or runtime.output.quiet |
| 181 | runtime.output.verbose = args.verbose or runtime.output.verbose |
| 182 | runtime.output.no_color = args.no_color or runtime.output.no_color |
| 183 | |
| 184 | if args.command == "init": |
| 185 | return run_init(args, runtime) |
| 186 | if args.command == "sync": |
| 187 | if args.diff is None: |
| 188 | args.diff = sys.stdout.isatty() |
| 189 | return run_sync(args, runtime) |
| 190 | if args.command == "status": |
| 191 | return run_status(args, runtime) |
| 192 | if args.command == "review": |
| 193 | return run_review(args, runtime, raw_argv=rest_argv) |
| 194 | if args.command == "governance-sync": |
| 195 | return run_governance_sync_command(args, runtime) |
| 196 | if args.command == "verify-step": |
| 197 | return run_verify_step_command(args, runtime) |
| 198 | if args.command == "honesty-status": |
| 199 | return run_honesty_status_command(args, runtime) |
| 200 | if args.command == "ledger": |
| 201 | return run_ledger_command(args, runtime) |
| 202 | |
| 203 | parser.error(f"unknown command: {args.command}") |
| 204 | return 1 |
| 205 | |
| 206 | |
| 207 | if __name__ == "__main__": |
| 208 | raise SystemExit(main()) |
File History
1 commit
sha256:4671b7f787ddbe63ced31c895b688c77ab495653b65a730b423329f26b3c1439
feat: K1-P1 complete — agent provenance, build-verification…
Sonnet 4.6
patch
58 days ago