CtrlK
BlogDocsLog inGet started
Tessl Logo

spec-driven-development/spec-as-source

Spec-driven development on OpenSpec, with mechanical spec-as-source enforcement: a custom 'spec-as-source' OpenSpec schema adds file-ownership (targets) and test-verification ([@test]) metadata to every capability spec, three scripts (link check, ownership check, manifest build) keep code and specs from drifting apart, plus requirement-gathering, spec-writer, work-review, and a session-handoff skill with a proactive context-warning hook.

68

Quality

85%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

run-round-2.shskills/plan-judge/scripts/

#!/usr/bin/env bash
# GENERATED FROM SPEC — DO NOT EDIT DIRECTLY
# Source: openspec/specs/plan-judge/spec.md
# Runs the fixed, container-isolated Round 2 development-document workflow.
set -euo pipefail

fatal() { echo "plan-judge: $*" >&2; exit 1; }

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
ROUND_DIR="$SKILL_DIR/prompts/round-2"
PROJECT_ROOT="${1:-$PWD}"
PROJECT_ROOT="$(cd "$PROJECT_ROOT" && pwd)"
INPUT_PLAN="${2:-$PROJECT_ROOT/.plan-judge/round-1/writer-4.md}"
if [ -f "$INPUT_PLAN" ]; then
    INPUT_PLAN="$(cd "$(dirname "$INPUT_PLAN")" && pwd)/$(basename "$INPUT_PLAN")"
fi
RUN_DIR="$PROJECT_ROOT/.plan-judge/round-2"
COMPOSE_BIN="${PLAN_JUDGE_COMPOSE_BIN:-docker compose}"
CODEX_BIN="${PLAN_JUDGE_CODEX_BIN:-codex}"
CLAUDE_BIN="${PLAN_JUDGE_CLAUDE_BIN:-claude}"

sha256() { shasum -a 256 "$1" | awk '{print $1}'; }

frontmatter_value() {
    awk -v key="$2" '
        $0 == "---" { delimiters++; next }
        delimiters == 1 && $0 ~ "^" key ": " {
            sub("^" key ": ", "")
            print
            exit
        }
    ' "$1"
}

compose_exec() {
    if [ "$COMPOSE_BIN" = "docker compose" ]; then
        docker compose exec -T code "$@"
    else
        "$COMPOSE_BIN" exec -T code "$@"
    fi
}

preflight() {
    compose_exec "$CODEX_BIN" login status >/dev/null 2>&1 \
        || fatal "PREFLIGHT: codex login status failed in container code"
    compose_exec "$CLAUDE_BIN" auth status >/dev/null 2>&1 \
        || fatal "PREFLIGHT: claude auth status failed in container code"
}

validate_artifact() {
    file="$1"
    turn="$2"
    role="$3"
    provider="$4"
    expected_digest="$5"

    [ -s "$file" ] || fatal "missing $role artifact for pass $turn: $file"
    [ "$(frontmatter_value "$file" round)" = "2" ] || fatal "invalid round in $file"
    [ "$(frontmatter_value "$file" giro)" = "$turn" ] || fatal "invalid giro in $file"
    [ "$(frontmatter_value "$file" ruolo)" = "$role" ] || fatal "invalid role in $file"
    [ "$(frontmatter_value "$file" provider)" = "$provider" ] || fatal "invalid provider in $file"
    actual_digest="$(frontmatter_value "$file" input_digest)"
    [ -n "$actual_digest" ] || fatal "missing input_digest in $file"
    [ "$actual_digest" = "sha256:$expected_digest" ] \
        || fatal "STALE-INPUT: $role artifact for pass $turn does not match its latest input"
}

run_provider() {
    provider="$1"
    role="$2"
    turn="$3"
    prompt="$4"
    input="$5"
    output="$6"
    digest="$7"

    instruction="Your context is fresh. Read instructions from $prompt. Read only input artifact $input. Write only output artifact $output. Its frontmatter MUST declare round: 2, giro: $turn, ruolo: $role, provider: $provider, input_digest: sha256:$digest. Do not edit openspec/PLAN.md."

    if [ "$provider" = "codex" ]; then
        PLAN_JUDGE_PROVIDER="$provider" PLAN_JUDGE_ROLE="$role" \
        PLAN_JUDGE_TURN="$turn" PLAN_JUDGE_PROMPT="$prompt" \
        PLAN_JUDGE_INPUT="$input" PLAN_JUDGE_OUTPUT="$output" \
        PLAN_JUDGE_EXPECTED_DIGEST="sha256:$digest" \
        compose_exec "$CODEX_BIN" exec "$instruction"
    else
        PLAN_JUDGE_PROVIDER="$provider" PLAN_JUDGE_ROLE="$role" \
        PLAN_JUDGE_TURN="$turn" PLAN_JUDGE_PROMPT="$prompt" \
        PLAN_JUDGE_INPUT="$input" PLAN_JUDGE_OUTPUT="$output" \
        PLAN_JUDGE_EXPECTED_DIGEST="sha256:$digest" \
        compose_exec "$CLAUDE_BIN" -p "$instruction"
    fi
}

validate_document() {
    file="$1"
    awk '
        function valid_choice() {
            return has_source && has_reason && has_goal
        }
        /^##[[:space:]]+Choice:/ {
            if (in_choice && !valid_choice()) exit 1
            in_choice = 1
            choices++
            has_source = has_reason = has_goal = 0
            next
        }
        in_choice && /^[[:space:]]*[-*]?[[:space:]]*Source:[[:space:]]*[^[:space:]]/ { has_source = 1 }
        in_choice && /^[[:space:]]*[-*]?[[:space:]]*Reason:[[:space:]]*[^[:space:]]/ { has_reason = 1 }
        in_choice && /^[[:space:]]*[-*]?[[:space:]]*Goal advantage:[[:space:]]*[^[:space:]]/ { has_goal = 1 }
        END { if (!choices || !valid_choice()) exit 1 }
    ' "$file" || fatal "INCOMPLETE-CHOICE: every technical choice needs Source, Reason and Goal advantage"
}

[ -f "$INPUT_PLAN" ] || fatal "missing rewritten Round 1 plan: $INPUT_PLAN"
for prompt in research.md verify.md writer.md goal-review.md; do
    [ -f "$ROUND_DIR/$prompt" ] || fatal "missing Round 2 prompt: $prompt"
done

preflight
mkdir -p "$RUN_DIR"
seed="$RUN_DIR/input-0.md"
cp "$INPUT_PLAN" "$seed"
current_input="$seed"

roles=(research verify writer goal-review)
# Each provider takes one producing role (research, writer) and one checking
# role (verify, goal-review): giving both producing roles to one provider would
# put only that model's generative output into the document, leaving the other
# to object without ever proposing an alternative.
providers=(codex claude claude codex)
prompts=(research.md verify.md writer.md goal-review.md)

for index in 0 1 2 3; do
    turn=$((index + 1))
    role="${roles[$index]}"
    provider="${providers[$index]}"
    prompt="$ROUND_DIR/${prompts[$index]}"
    output="$RUN_DIR/$role-$turn.md"
    digest="$(sha256 "$current_input")"
    run_provider "$provider" "$role" "$turn" "$prompt" "$current_input" "$output" "$digest"
    validate_artifact "$output" "$turn" "$role" "$provider" "$digest"
    current_input="$output"
done

final_document="$RUN_DIR/DOCUMENTOSVILUPPO.MD"
cp "$current_input" "$final_document"
validate_document "$final_document"
echo "plan-judge: Round 2 complete: $final_document"

README.md

tile.json