← the whole session plugin/skills/declare-scope/SKILL.md

Decompose a task into testable UX intent statements and post to compaction. Use at the start of every non-trivial task.

Declare Scope

Before your output, print ## SCOPE_DECLARATION on its own line. This enables automated extraction to the compaction admin UI.

After your scope output is complete, print ## END_SCOPE_DECLARATION on its own line. This closes the extraction block.

One function. Reason about the human's intent, decompose it, post it, print it.

When to invoke

  • At the start of every non-trivial task (governer score >= 20)
  • When the human changes direction mid-session
  • When you realize your understanding was wrong

What you do

Step 1: Reason

REQUIRED: Consume /how-to-articulate-intent before writing any statements. That skill defines the format, wrong/right examples, and rules.

Decompose the human's request into atomic statements using the two formats:

  • System intent: When {every condition as experienced} then {system, named by function} should {behavior as effect on person}
  • UX intent: When {every condition as person's state} then {the person} should {what happens for them, code-precise in human terms}

Rules for each statement:

  • Atomic — one testable thing
  • Precise — as specific as code
  • Human-readable — any stakeholder can understand it
  • Never use code variable names when a UX-equivalent exists
    • Wrong: "when accountTier === 1 and billingCustomerId exists"
    • Right: "when the user is on the free tier and has a payment method on file"

Auto-mining triggers — when the human says any of these, an intent exists to be captured:

Pattern Example
"users should never..." "users should never see a blank screen after paying"
"users should always..." "users should always know their trial status"
"when X happens, they should see Y" "when they upgrade, they should see a confirmation"
"never show X when Y" "never show upgrade CTA to a paying user"
"this is broken because [UX description]" "this is broken because free users see paid features"

Step 2: Post — use declareScope() function

Run the function below. It resolves the session ID, validates the inputs, and writes the declaration to a local record so it survives past this chat window — no server or API key required. If you've wired your own Intent DB or compaction API (see /intent-db, if you've set one up), it's an optional add-on you layer on top of this, not a replacement for it — the local write always happens first and always succeeds on its own.

# Call this function — do NOT manually construct curl calls
declareScope() {
  # --- Resolve session ID the harness's own way (works with no other setup) ---
  local SESSION_ID
  SESSION_ID=$(alignment-harness session-id 2>/dev/null)
  if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "unknown-session" ]; then
    echo "⚠️ DECLARE-SCOPE: no session id resolved (alignment-harness not on PATH, or hooks not running) — using a generated id for this record"
    SESSION_ID="session-$(date +%s)"
  fi

  local SUMMARY="$1"        # one-line summary of what the human asked for
  local DECOMPOSED="$2"     # JSON array: ["When X → Y", "When A → B"]
  local BOUNDARY="$3"       # what is NOT in scope
  local VERIFICATION="$4"   # runnable command that proves it works
  local CERTAINTY="${5:-85}" # 0-100

  # --- Validate inputs ---
  if [ -z "$SUMMARY" ] || [ -z "$DECOMPOSED" ]; then
    echo "❌ DECLARE-SCOPE FAILED: Missing required arguments"
    echo "  → Usage: declareScope 'summary' '[\"When X → Y\"]' 'boundary' 'verification' 85"
    echo "  → You must provide at least summary and decomposed statements"
    return 1
  fi

  local INTENT_COUNT=$(echo "$DECOMPOSED" | jq 'length' 2>/dev/null || echo 0)

  # --- Write the local record (this is the primary, always-on persistence) ---
  local RECORDS_DIR
  RECORDS_DIR=$(alignment-harness records scope-declarations 2>/dev/null)
  if [ -z "$RECORDS_DIR" ]; then
    echo "❌ DECLARE-SCOPE: could not resolve the records folder — is alignment-harness on PATH?"
    echo "  → Falling back to printing the declaration only; nothing was saved."
    return 1
  fi
  mkdir -p "$RECORDS_DIR"
  local OUT_FILE="$RECORDS_DIR/${SESSION_ID}-$(date +%s).json"

  jq -n \
    --arg sessionId "$SESSION_ID" \
    --arg summary "$SUMMARY" \
    --argjson decomposed "$DECOMPOSED" \
    --arg boundary "${BOUNDARY:-not specified}" \
    --arg verification "${VERIFICATION:-not specified}" \
    --argjson certainty "$CERTAINTY" \
    --arg postedAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
    '{
      sessionId: $sessionId,
      summary: $summary,
      decomposed: $decomposed,
      boundary: $boundary,
      verification: $verification,
      certainty: $certainty,
      postedAt: $postedAt
    }' > "$OUT_FILE"

  local WRITE_OK=1
  if [ ! -s "$OUT_FILE" ]; then
    WRITE_OK=0
  fi

  # --- Optional: if the person has their own Intent DB / compaction API configured, sync to it too ---
  # This is additive and never blocks the local write above. If /intent-db (or your own
  # equivalent) isn't set up, skip this silently — the local record is already the source of truth.

  # --- Report back to the invoking agent ---
  echo ""
  echo "━━━ DECLARE-SCOPE RESULT ━━━"
  echo "Session: $SESSION_ID"
  echo "Statements in this scope: $INTENT_COUNT"
  if [ "$WRITE_OK" = "1" ]; then
    echo "Saved: $OUT_FILE"
  else
    echo "❌ Local write FAILED — $OUT_FILE is empty or missing. Check that $RECORDS_DIR is writable."
  fi
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━"

  if [ "$WRITE_OK" != "1" ]; then
    return 1
  fi
  return 0
}

How to use:

declareScope \
  "Unify intent lifecycle and scope declaration into one skill" \
  '["When an agent starts a task → it decomposes intent and writes a local scope record in one call", "When the scope is saved → it prints to chat so the human can correct in real-time", "When saving fails → the error and next step are reported back to the agent"]' \
  "Not changing the Intent DB schema or the plugin's own record format" \
  "cat the saved JSON file and confirm the decomposed/boundary/verification/certainty fields are populated" \
  90

Step 3: Print to chat

After calling declareScope(), print the decomposition to the human. The function reports success/failure, but YOU print the human-readable scope:

📋 Scope: {one-line summary of what the human asked for}

When {constraints} → {testable UX outcome}
When {constraints} → {testable UX outcome}
When {constraints} → {testable UX outcome}

Boundary: {what is NOT in scope}
Verification: {runnable command that proves it works}
Certainty: {0-100} — {why this number}

Do NOT block waiting for approval — /governer decides whether to act or propose.

Certainty scale:

  • 95-100: Human was explicit, requirements unambiguous
  • 85-94: Clear intent, some details need assumptions — state them
  • 70-84: Direction clear, specifics fuzzy — reflect, then proceed with best prediction
  • Below 70: Predict the most likely intent, propose it as default assumption, proceed. NEVER stop to ask.

Step 4: Governer

After printing, invoke /governer on the first decomposed task. Governer scores it and decides: act directly or propose for human review.

Error handling

Every failure reports back to you with:

  • What failed (Intent DB write, compaction write, session ID resolution)
  • Why (the actual error message from the API)
  • What to do next (specific fix action)

If declareScope() returns non-zero, read the error output and fix the issue before proceeding. Do NOT ignore errors and claim scope was posted.

Two-Layer ID System

Every intent gets two identifiers. Pick a short prefix for your own project at setup (your project's initials, or a plain running number) — the examples below use PROJ- as a placeholder:

  • Machine layer: PROJ-042 (3-4 tokens) — use in code comments (// @intent: PROJ-042), commits (Intents: PROJ-042), agent context
  • Human layer: Full UX statement — use in test names, UX assignments, changelogs, chat

If you have an Intent DB set up (see /intent-db), it resolves the ID to the full intent record. Without one, the local scope-declaration record (below) and git log --grep are the registry.

Intent Through Phases

Phase What happens with intent
Discovery Decompose → post → print (this skill)
Planning Reference the intent ID in the plan, flag gaps
Implementation Tag code: // @intent: PROJ-042 at entry points and error paths
TDD Test file header: @intents-covered: PROJ-042, PROJ-043
Commit Body includes Intents: PROJ-042
Audit git log --grep="Intents:" --oneline traces intent through commits

Where the record lives

After posting, the function prints the path it saved to — a JSON file under the folder alignment-harness records scope-declarations prints. Open that file directly, or grep across the folder, to see every scope this project has declared. There's no admin UI required for this to work; if you've built one on top of your own Intent DB setup, point it at that same folder or your synced copy.