Skip to content

Enhancement: Add persistent SDLC pointer + guarded-run wrapper (/sdlc-set-pointer) #19

Description

@jmjava

Summary

The repository currently has a proposed shell script to add a persistent "pointer" (current chore/task) and guarded wrappers so agent commands only execute against the current pointer. This issue adds a spell-checked, syntax-improved version of that script, usage examples, and suggested next steps (PR to add the script under agent-context/ and optionally wire it into initialization).

Why

Agents can get confused and start working on older chores/tasks. A persistent pointer plus guarded wrappers ensure commands only run against the intended chore until the pointer is explicitly changed or reset.

What I changed (spell/syntax improvements)

  • Fixed typos and clarified comments and messages.
  • Improved locking usage and fallbacks for environments without flock.
  • Made variable expansion and quoting safer.
  • Improved CLI parsing and usage output.

Proposed script (place as agent-context/sdlc-pointer.sh)

#!/usr/bin/env bash
# Simple pointer manager for SDLC chores/tasks
# Usage:
#   source agent-context/sdlc-pointer.sh
#   sdlc_init                          # call on initialization
#   sdlc_set_pointer ID                # sets pointer
#   sdlc_get_pointer                   # prints pointer or empty
#   sdlc_reset_pointer                 # clears pointer
#   run_against_pointer "<expected>" -- <command...>
#
# Default storage: .sdlc/pointer in the repository root.

set -euo pipefail

SDLC_ROOT="${SDLC_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
SDLC_DIR="${SDLC_DIR:-${SDLC_ROOT}/.sdlc}"
SDLC_POINTER="${SDLC_DIR}/pointer"
SDLC_LOCK="${SDLC_DIR}/pointer.lock"

mkdir -p "${SDLC_DIR}"

_have_flock() {
  command -v flock >/dev/null 2>&1
}

sdlc_get_pointer() {
  if [ ! -f "${SDLC_POINTER}" ]; then
    printf ""
    return 0
  fi
  cat "${SDLC_POINTER}"
}

sdlc_set_pointer() {
  local new="${1:-}"
  if [ -z "${new}" ]; then
    echo "sdlc_set_pointer: missing pointer id" >&2
    return 2
  fi
  if _have_flock; then
    # Use flock if available for atomic write
    flock --exclusive --timeout 5 "${SDLC_LOCK}" -c "printf '%s' '${new}' > '${SDLC_POINTER}'"
  else
    # Fallback: write to temp file then move
    tmpfile="${SDLC_POINTER}.$(date +%s).tmp"
    printf '%s' "${new}" > "${tmpfile}"
    mv -f "${tmpfile}" "${SDLC_POINTER}"
  fi
  echo "pointer set to: ${new}"
}

sdlc_reset_pointer() {
  if _have_flock; then
    flock --exclusive --timeout 5 "${SDLC_LOCK}" -c "rm -f '${SDLC_POINTER}'"
  else
    rm -f "${SDLC_POINTER}" 2>/dev/null || true
  fi
  echo "pointer cleared"
}

sdlc_init() {
  if [ -n "${SDLC_POINTER_OVERRIDE:-}" ]; then
    sdlc_set_pointer "${SDLC_POINTER_OVERRIDE}"
  fi
}

run_against_pointer() {
  local expected
  expected="${1:-}"
  shift || true
  if [ "${1:-}" = "--" ]; then shift; fi
  if [ -z "${expected}" ]; then
    echo "run_against_pointer: expected pointer id required" >&2
    return 2
  fi
  local current
  if _have_flock; then
    current=$(flock --shared --timeout 5 "${SDLC_LOCK}" -c "cat '${SDLC_POINTER}' 2>/dev/null || true")
  else
    current=$(cat "${SDLC_POINTER}" 2>/dev/null || true)
  fi
  if [ "${current}" != "${expected}" ]; then
    echo "Pointer mismatch: current='${current}' expected='${expected}' — refusing to run" >&2
    return 3
  fi
  # Execute the command
  "$@"
}

# CLI when script executed directly
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
  cmd="${1:-}"; shift || true
  case "${cmd}" in
    set|/sdlc-set-pointer) sdlc_set_pointer "$@" ;;
    get|/sdlc-get-pointer) sdlc_get_pointer ;;
    reset|/sdlc-reset-pointer) sdlc_reset_pointer ;;
    init|/sdlc-init) sdlc_init ;;
    run|/sdlc-run)
      expected="${1:-}"; shift || true
      run_against_pointer "${expected}" -- "$@" ;;
    *)
      echo "Usage: $0 {set|get|reset|init|run} ..." >&2
      exit 2 ;;
  esac
fi

Usage examples

  • Set pointer: /sdlc-set-pointer chore-123
  • Guarded run: run_against_pointer "chore-123" -- ./do-work.sh
  • Initialize on agent start: source agent-context/sdlc-pointer.sh && sdlc_init

Next steps

  • Add the script to agent-context/ and a short README snippet showing how to source and use it.
  • Optionally decide whether pointer changes should be committed to the repo history (git commit) or left as local state.
  • Optionally add ACL controls and an idempotency token if multiple distributed agents will interact with the pointer.

Acceptance criteria

  • A new issue exists with the spell-checked script, usage notes, and clear next steps.
  • The script path suggestion is agent-context/sdlc-pointer.sh and is ready to be added in a follow-up PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions