framework tools/git: issue-list, milestone-create, lane-brief R1/R4 conversions (P1 complete)

- issue-list + milestone-create: usage() default exit 2, value guards,
  missing-title via usage_error.
- lane-brief: getopts replaced with a while/case parser carrying R2
  long-flag aliases (--repo --milestone --label/--labels --login
  --limit) beside the short forms; login-resolution failure reclassified
  from exit 2 to exit 1 (credential class, not an invocation defect).
- Three suites enrolled (population 88); lane-brief pr-linkage suite
  still ALL PASS; green in both trees; mirrored to the brain tree.

With this, every agent-facing wrapper in tools/git carries the R1/R4
usage-error contract (22/22 non-guard wrappers; guards keep their own
contracts).
This commit is contained in:
2026-08-28 18:10:27 -05:00
parent bb23cb6feb
commit c8b4af59c3
7 changed files with 418 additions and 16 deletions
@@ -37,21 +37,31 @@ Examples:
$(basename "$0") -t "0.0.1" -d "Pre-MVP Foundation Sprint"
$(basename "$0") -t "0.1.0" -d "MVP Release" --due "2025-03-01"
EOF
exit "${1:-1}"
exit "${1:-2}"
}
# Parse arguments
# Usage-error contract (R4, 2026-08-28): usage errors print to STDERR and exit 2,
# distinct from provider, credential, and verification failures (exit 1).
usage_error() {
echo "Error: $*" >&2
usage
}
while [[ $# -gt 0 ]]; do
case $1 in
-t|--title)
[[ $# -ge 2 ]] || usage_error "option $1 requires a value"
TITLE="$2"
shift 2
;;
-d|--desc)
[[ $# -ge 2 ]] || usage_error "option $1 requires a value"
DESCRIPTION="$2"
shift 2
;;
--due)
[[ $# -ge 2 ]] || usage_error "option $1 requires a value"
DUE_DATE="$2"
shift 2
;;
@@ -92,8 +102,7 @@ if [[ "$LIST_ONLY" == true ]]; then
fi
if [[ -z "$TITLE" ]]; then
echo "Error: Title is required (-t) for creating milestones" >&2
usage
usage_error "Title is required (-t) for creating milestones"
fi
case "$PLATFORM" in