From 4b5c3d49f35730ea279c853b6dd122920d574b8c Mon Sep 17 00:00:00 2001 From: Bo Date: Fri, 29 May 2026 19:43:41 -0400 Subject: [PATCH] feat(skills): skill-builder scaffolds dispositions row + narrative counts (ag-cw2y items 1-scaffold + 2) Completes the scaffold-half of ag-cw2y item 1 and item 2: a newly-scaffolded skill is now one-shot-green against the two gates that silently tripped /burndown #600. - scripts/append-skill-disposition.sh: idempotent helper that appends a skill-dispositions.yaml row (valid BC4 placeholder + TODO rationale) if the skill has none. Repo-root-injectable for testing. - init.sh: after scaffolding, calls the helper (pairs with #609's heal.sh Check 12) AND runs check-registry-drift.sh --fix-counts (bumps the 'N checked-in skills' narrative tokens in domain-map + bdd Gherkin so the new skill doesn't trip registry-drift). - Discovery: item 2's CHECK + --fix-counts already existed and were wired into both the fast gate and CI; the gap was only that skill-builder never invoked them. No new check needed. Codex artifact: refreshed skill-builder source/generated hash only (6 unrelated pre-existing main drifts left untouched). PR-scope codex validation passes. Closes-scenario: ag-cw2y#skillbuilder-scaffold-dispositions-counts Bounded-context: BC4-factory Evidence: tests/scripts/append-skill-disposition.bats --- scripts/append-skill-disposition.sh | 36 ++++++++++++++ skills-codex/.agentops-manifest.json | 2 +- .../skill-builder/.agentops-generated.json | 2 +- skills/skill-builder/scripts/init.sh | 15 ++++++ tests/scripts/append-skill-disposition.bats | 49 +++++++++++++++++++ 5 files changed, 102 insertions(+), 2 deletions(-) create mode 100755 scripts/append-skill-disposition.sh create mode 100644 tests/scripts/append-skill-disposition.bats diff --git a/scripts/append-skill-disposition.sh b/scripts/append-skill-disposition.sh new file mode 100755 index 000000000..46bf3b7d5 --- /dev/null +++ b/scripts/append-skill-disposition.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# append-skill-disposition.sh — ensure a new skill has a row in +# docs/contracts/skill-dispositions.yaml (ag-cw2y item-1 scaffold-half). +# +# Idempotent: appends a placeholder row only if the skill has none, so a +# newly-scaffolded skill is one-shot-green against heal.sh Check 12 +# (MISSING_DISPOSITION). The placeholder uses a real bounded context so +# check-bounded-contexts-drift.sh passes; the author refines domain / +# hexagonal_role / disposition / rationale during content fill (mirrors the +# "manual content fill required" contract of the SKILL.md skeleton). +# +# Usage: append-skill-disposition.sh [repo-root] +set -euo pipefail + +SKILL="${1:?usage: append-skill-disposition.sh [repo-root]}" +REPO_ROOT="${2:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}" +FILE="$REPO_ROOT/docs/contracts/skill-dispositions.yaml" + +if [[ ! -f "$FILE" ]]; then + echo "append-skill-disposition: no dispositions file at $FILE" >&2 + exit 1 +fi + +if grep -qE "^[[:space:]]*-[[:space:]]+skill:[[:space:]]+${SKILL}[[:space:]]*$" "$FILE"; then + echo "append-skill-disposition: '$SKILL' already present — no-op" + exit 0 +fi + +cat >> "$FILE" < "$BUILD_REPORT" <&2 +fi +# 2. Narrative skill counts — --fix-counts bumps the "N checked-in skills" tokens +# in the domain-map + bdd Gherkin so the new skill doesn't trip registry-drift. +if [[ -x "$REPO_ROOT/scripts/check-registry-drift.sh" ]]; then + bash "$REPO_ROOT/scripts/check-registry-drift.sh" --fix-counts >/dev/null 2>&1 \ + || echo "init.sh: WARN registry-drift --fix-counts could not run — bump counts manually" >&2 +fi + echo "init.sh: created skill skeleton at $NEW_DIR" echo "init.sh: codex parity at $CODEX_DIR" echo "init.sh: build report at $BUILD_REPORT" +echo "init.sh: dispositions row + narrative counts scaffolded (refine the placeholder row)" diff --git a/tests/scripts/append-skill-disposition.bats b/tests/scripts/append-skill-disposition.bats new file mode 100644 index 000000000..0b7e4c7a2 --- /dev/null +++ b/tests/scripts/append-skill-disposition.bats @@ -0,0 +1,49 @@ +#!/usr/bin/env bats +# ag-cw2y item-1 scaffold-half: skill-builder must append a skill-dispositions.yaml +# row for a new skill so it is one-shot-green against heal.sh Check 12. The helper +# is idempotent and repo-root-injectable (so init.sh can call it and tests can +# fixture it). + +setup() { + HELPER="$BATS_TEST_DIRNAME/../../scripts/append-skill-disposition.sh" + FIX="$(mktemp -d)" + mkdir -p "$FIX/docs/contracts" + cat > "$FIX/docs/contracts/skill-dispositions.yaml" <<'EOF' +dispositions: + - skill: existing + domain: "BC1 Corpus" + hexagonal_role: domain + disposition: keep + rationale: "already here" +EOF +} + +teardown() { rm -rf "$FIX"; } + +@test "appends a dispositions row for a new skill" { + run bash "$HELPER" newskill "$FIX" + [ "$status" -eq 0 ] + grep -qE "^[[:space:]]*-[[:space:]]+skill:[[:space:]]+newskill[[:space:]]*$" "$FIX/docs/contracts/skill-dispositions.yaml" +} + +@test "appended row carries a valid BC domain and a TODO rationale" { + bash "$HELPER" newskill "$FIX" + # The row's domain must be a real bounded context (so check-bounded-contexts-drift passes) + run grep -A4 'skill: newskill' "$FIX/docs/contracts/skill-dispositions.yaml" + [[ "$output" == *"BC4 Factory"* ]] + [[ "$output" == *"TODO"* ]] +} + +@test "is idempotent — running twice does not duplicate the row" { + bash "$HELPER" newskill "$FIX" + bash "$HELPER" newskill "$FIX" + count=$(grep -cE "^[[:space:]]*-[[:space:]]+skill:[[:space:]]+newskill[[:space:]]*$" "$FIX/docs/contracts/skill-dispositions.yaml") + [ "$count" -eq 1 ] +} + +@test "does not touch an already-present skill" { + run bash "$HELPER" existing "$FIX" + [ "$status" -eq 0 ] + count=$(grep -cE "^[[:space:]]*-[[:space:]]+skill:[[:space:]]+existing[[:space:]]*$" "$FIX/docs/contracts/skill-dispositions.yaml") + [ "$count" -eq 1 ] +}