Step 1 of the control-marking task, and deliberately server-only: no handle is drawn yet. This project already shipped a range handle for `profile.interval`, which compileGeometry ignores, so the control dragged and changed nothing. The consumer comes first now. Two kinds join the taxonomy — `junction-crosswalk-inset` and `junction-stop-line-offset`, both on the existing `junction-approach` anchor. The solver writes them onto the approach entry, `applyDirectJunctionPlans` carries them onto the compiled approach, and `compileControlMarkings` reads them in place of the module constants it used for every junction. They move markings without reshaping the junction, so unlike width and cutback they deliberately do not trigger a boundary recompute. `applyJunctionConstraint` becomes an explicit switch. Its trailing `else` had meant every kind that was not approach-width fell through to the cutback validator, so a new kind would have been silently validated and written as a cutback. The same non-exhaustive shape in the test fixture's `valueFor` is fixed the same way, and now throws for an unnamed kind rather than answering with a corner radius. design.md's taxonomy is updated with it — a test asserts the two cannot drift, which is what caught the omission. Measured on a 41-road workspace with 8 crossings: both constraints change their marking geometry, neither drags the other, and out-of-range blocks instead of clamping. That measurement is not in the suite: the synthetic junction resolves `junction_inset_m` to 0 because its crossing never binds to a plan, and the committed OSM fixture has no crossings at all. The tests assert the wiring the handles will depend on — values reaching the approach entry, distinct branches, blocking diagnostics — and the gap is recorded in the test itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
107 lines
3.0 KiB
Python
Executable File
107 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Git and Session Context utilities.
|
|
|
|
Entry shim — delegates to session_context and packages_context.
|
|
|
|
Provides:
|
|
output_json - Output context in JSON format
|
|
output_text - Output context in text format
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from .git import run_git
|
|
from .session_context import (
|
|
get_context_json,
|
|
get_context_text,
|
|
get_context_record_json,
|
|
get_context_text_record,
|
|
output_json,
|
|
output_text,
|
|
)
|
|
from .packages_context import (
|
|
get_context_packages_text,
|
|
get_context_packages_json,
|
|
)
|
|
from .trellis_config import read_trellis_config
|
|
from .workflow_phase import (
|
|
filter_platform,
|
|
get_phase_index,
|
|
get_step,
|
|
resolve_effective_platform,
|
|
)
|
|
|
|
# Backward-compatible alias — external modules import this name
|
|
_run_git_command = run_git
|
|
|
|
|
|
# =============================================================================
|
|
# Main Entry
|
|
# =============================================================================
|
|
|
|
def main() -> None:
|
|
"""CLI entry point."""
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description="Get Session Context for AI Agent")
|
|
parser.add_argument(
|
|
"--json",
|
|
"-j",
|
|
action="store_true",
|
|
help="Output in JSON format (works with any --mode)",
|
|
)
|
|
parser.add_argument(
|
|
"--mode",
|
|
"-m",
|
|
choices=["default", "record", "packages", "phase"],
|
|
default="default",
|
|
help="Output mode: default (full context), record (for record-session), packages (package info only), phase (workflow step extraction)",
|
|
)
|
|
parser.add_argument(
|
|
"--step",
|
|
help="Step id for --mode phase, e.g. 1.1, 2.2. Omit to get the Phase Index.",
|
|
)
|
|
parser.add_argument(
|
|
"--platform",
|
|
help="Platform name for --mode phase, e.g. cursor, claude-code. Filters platform-tagged blocks.",
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.mode == "record":
|
|
if args.json:
|
|
print(json.dumps(get_context_record_json(), indent=2, ensure_ascii=False))
|
|
else:
|
|
print(get_context_text_record())
|
|
elif args.mode == "packages":
|
|
if args.json:
|
|
print(json.dumps(get_context_packages_json(), indent=2, ensure_ascii=False))
|
|
else:
|
|
print(get_context_packages_text())
|
|
elif args.mode == "phase":
|
|
content = get_step(args.step) if args.step else get_phase_index()
|
|
if not content.strip():
|
|
if args.step:
|
|
parser.exit(2, f"Step not found: {args.step}\n")
|
|
else:
|
|
parser.exit(2, "Phase Index section not found in workflow.md\n")
|
|
if args.platform:
|
|
effective = resolve_effective_platform(
|
|
args.platform, read_trellis_config()
|
|
)
|
|
content = filter_platform(content, effective)
|
|
print(content, end="")
|
|
else:
|
|
if args.json:
|
|
output_json()
|
|
else:
|
|
output_text()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|