feat: migrate missing harnesses, templates, and workflows from agent-runtimes

Brings the framework CRS repo up to date with all content that was
living in agent-runtimes (local-dev fallback) but hadn't been promoted.

New composites: feature-delivery-loop, integration-direct, scaffolding-repo,
sonnet-impl-narrow, sonnet-manager, test-writing-repo

New contexts: integration/v1, scaffolding/v1, sonnet-manager/v1, z-ai/v1,
airouter/v1/bin (anthropic-compat-wrapper.sh), cp-harness/v1/init.sh

New task-templates: sonnet-integrator.yaml, workflow/* (17 typed workflow
task templates for the Epic 1 pipeline)

Updated: agent-repo/v1/finalize.sh — adds AR-38/F97 empty-deliverable audit
(SKIP_BRANCH_PUSH support, boilerplate-path filtering, ci_metadata.json flag)

Also adds MEMORY.md index and memory/ topic files for the framework repo.
This commit is contained in:
Paul O'Reilly
2026-06-23 08:59:01 +12:00
parent 770ba97170
commit f5968cfab5
45 changed files with 1566 additions and 101 deletions

View File

@@ -1,8 +1,18 @@
#!/bin/bash
# Agent repo finalize script — auto-commit and push changes
# AR-19, AR-20, AR-8, AR-32, F66, BUG-5, BUG-20
# AR-19, AR-20, AR-8, AR-32, AR-38, F66, F97, BUG-5, BUG-20
set -euo pipefail
# ---------------------------------------------------------------------------
# AR-38 / F97: Post-commit empty-deliverable audit configuration
# Paths matching this regex are treated as boilerplate / metadata only —
# a commit containing ONLY paths matching this pattern is rejected.
# Overridable so harnesses with a different notion of "trivial" can adjust
# without forking this script.
# ---------------------------------------------------------------------------
DEFAULT_BOILERPLATE_PATHS_REGEX='^(\.gitignore|AGENTS\.md|ci_metadata\.json|memory/log/.*|\.agent-output/.*)$'
BOILERPLATE_PATHS_REGEX="${AGENT_BOILERPLATE_PATHS_REGEX:-$DEFAULT_BOILERPLATE_PATHS_REGEX}"
# ---------------------------------------------------------------------------
# F66: Content-based secret scanning
# Scans staged diff for credential patterns before committing.
@@ -59,6 +69,9 @@ BRANCH="${AGENT_BRANCH:-}"
REPO_URL="${AGENT_REPO_URL:-}"
# BUG-20: Push retry
PUSH_RETRIES="${AGENT_PUSH_RETRIES:-1}"
# When true, skip the branch push entirely (e.g. direct-push integrators that
# push to origin main themselves rather than using branch persistence).
SKIP_BRANCH_PUSH="${AGENT_SKIP_BRANCH_PUSH:-false}"
mkdir -p "$AGENT_OUTPUT_DIR"
@@ -146,6 +159,16 @@ fi
# Check again after potential moves
if [ -z "$(git status --porcelain)" ]; then
echo "No changes to commit — skipping push (AR-8)"
# AR-38 / F97: AR-8 no-commit path is semantically equivalent to
# "empty deliverable" — the agent produced no work product at all.
# When the audit is enabled, surface this as empty_deliverable=true so
# operators triaging via ci_metadata.json can distinguish "agent did
# nothing" from "audit disabled by operator config" (the only path
# that produces an absent key).
AR8_EMPTY_DELIVERABLE_ENABLED="true"
if [ "${AGENT_EMPTY_DELIVERABLE_CHECK:-true}" = "false" ]; then
AR8_EMPTY_DELIVERABLE_ENABLED="false"
fi
python3 -c "
import json, os
out = '$METADATA_FILE'
@@ -159,6 +182,8 @@ if os.path.isfile(out):
meta['agent_branch'] = '$BRANCH'
meta['agent_repo_url'] = '$REPO_URL'
meta['agent_branch_pushed'] = False
if '$AR8_EMPTY_DELIVERABLE_ENABLED' == 'true':
meta['empty_deliverable'] = True
with open(out, 'w') as f:
json.dump(meta, f)
print('Wrote ci_metadata.json (no-op: no changes)')
@@ -238,6 +263,44 @@ git commit -F "$COMMIT_MSG_FILE"
COMMIT_SHA=$(git rev-parse HEAD)
echo "Committed as: $COMMIT_SHA"
# AR-38 / F97: Post-commit empty-deliverable audit ------------------------
# Inspect the committed diff. If every changed path is boilerplate
# (.gitignore, AGENTS.md, ci_metadata.json, memory/log/*, .agent-output/*),
# flag the commit as empty_deliverable so the operator can distinguish a
# real successful run from a no-op that happened to advance HEAD.
#
# Sentinel values for EMPTY_DELIVERABLE:
# "true" — audit ran, every committed path was boilerplate
# "false" — audit ran, at least one path was substantive
# "skipped" — audit disabled by AGENT_EMPTY_DELIVERABLE_CHECK=false
#
# Wrapped in `set +eo pipefail` because a piped grep that finds nothing
# returns 1, which would otherwise abort the script (see gotchas-agent-repo
# "AR-21 set-e/pipefail aborts finalize on diff-verify pipeline").
EMPTY_DELIVERABLE="false"
if [ "${AGENT_EMPTY_DELIVERABLE_CHECK:-true}" = "false" ]; then
echo "AR-38: empty-deliverable audit disabled by AGENT_EMPTY_DELIVERABLE_CHECK=false"
EMPTY_DELIVERABLE="skipped"
else
set +eo pipefail
COMMITTED_PATHS=$(git diff-tree --no-commit-id --name-only -r "$COMMIT_SHA")
SUBSTANTIVE_PATHS=$(printf '%s\n' "$COMMITTED_PATHS" \
| grep -v '^[[:space:]]*$' \
| grep -vxE "$BOILERPLATE_PATHS_REGEX")
set -eo pipefail
if [ -z "$SUBSTANTIVE_PATHS" ]; then
echo "ERROR: AR-38 empty-deliverable audit FAILED for commit $COMMIT_SHA" >&2
echo "ERROR: every committed path matched the boilerplate regex:" >&2
echo "ERROR: regex: $BOILERPLATE_PATHS_REGEX" >&2
echo "ERROR: committed paths:" >&2
printf '%s\n' "$COMMITTED_PATHS" | sed 's/^/ERROR: /' >&2
EMPTY_DELIVERABLE="true"
else
echo "AR-38: audit passed — substantive path(s) found in commit:"
printf '%s\n' "$SUBSTANTIVE_PATHS" | sed 's/^/ /'
fi
fi
# BUG-20: Output validation — check expected output file exists and is non-empty
# AGENT_EXPECTED_OUTPUT: absolute path to required output file (e.g., /workspace/project/spec/f94-auth.md)
# AGENT_MIN_OUTPUT_BYTES: minimum size in bytes (default 0 = any non-empty)
@@ -260,79 +323,31 @@ if [ -n "${AGENT_EXPECTED_OUTPUT:-}" ]; then
fi
fi
# AR-21 (2026-05-08): Diff-against-upstream verification.
# AGENT_EXPECTED_CHANGED_FILES: comma-separated list of paths that MUST appear
# in the working-tree diff vs upstream main. Catches the failure mode where
# an agent reports "succeeded" but produced no actual change to the target
# file (real incident: 2026-05-08 dogfood batch, gotchas item 30 — three
# "succeeded" tasks merged nothing actionable).
# AGENT_FORBIDDEN_CHANGED_FILES: comma-separated list of paths that MUST NOT
# appear in the diff. Catches the inverse: an agent silently destroying or
# refactoring files outside the task scope (real incident: 2026-05-08 task
# 4a2f2988 — agent stripped 9 unrelated functions; gotchas item 17/21).
#
# Whole block runs with set +e (and pipefail off) to ensure no diagnostic
# pipeline failure aborts finalize before metadata can be written. We
# explicitly check exit codes where they matter.
DIFF_VERIFIED=true
DIFF_MISMATCH=""
DIFF_SUMMARY=""
set +eo pipefail
if [ -d /workspace/reference/main/.git ]; then
REF_HEAD=$(git -C /workspace/reference/main rev-parse HEAD 2>/dev/null)
if [ -n "$REF_HEAD" ]; then
# Files modified/added/deleted by the agent vs the upstream HEAD seed.
# Use git diff (working-tree style) plus committed changes — the
# agent commits via finalize.sh later, so the diff against REF_HEAD
# reflects total scope. `|| true` belt-and-braces against unreachable
# SHAs (e.g., if init.sh fell back to fork main without seeding from
# upstream).
DIFF_RAW=$(git diff --name-only "$REF_HEAD"..HEAD 2>/dev/null || true)
# If the .. range fails (rev-parse error) the substitution returns "".
# Fall back to the simpler diff against working-tree HEAD-1 (no good
# answer; just emit empty).
DIFF_SUMMARY=$(printf '%s\n' "$DIFF_RAW" | tr '\n' ',' | sed 's/,$//' || true)
if [ -n "${AGENT_EXPECTED_CHANGED_FILES:-}" ]; then
echo "Verifying required changed files: $AGENT_EXPECTED_CHANGED_FILES"
IFS=',' read -ra _REQUIRED <<< "$AGENT_EXPECTED_CHANGED_FILES"
for required in "${_REQUIRED[@]:-}"; do
required="${required#"${required%%[![:space:]]*}"}"
required="${required%"${required##*[![:space:]]}"}"
[ -z "$required" ] && continue
if ! printf ',%s,' "$DIFF_SUMMARY" | grep -qF ",$required,"; then
echo "ERROR: Required change to '$required' missing from agent's diff"
DIFF_VERIFIED=false
DIFF_MISMATCH="$DIFF_MISMATCH missing:$required"
fi
done
fi
if [ -n "${AGENT_FORBIDDEN_CHANGED_FILES:-}" ]; then
echo "Verifying forbidden files unchanged: $AGENT_FORBIDDEN_CHANGED_FILES"
IFS=',' read -ra _FORBIDDEN <<< "$AGENT_FORBIDDEN_CHANGED_FILES"
for forbidden in "${_FORBIDDEN[@]:-}"; do
forbidden="${forbidden#"${forbidden%%[![:space:]]*}"}"
forbidden="${forbidden%"${forbidden##*[![:space:]]}"}"
[ -z "$forbidden" ] && continue
if printf ',%s,' "$DIFF_SUMMARY" | grep -qF ",$forbidden,"; then
echo "ERROR: Forbidden file '$forbidden' was modified by agent"
DIFF_VERIFIED=false
DIFF_MISMATCH="$DIFF_MISMATCH forbidden:$forbidden"
fi
done
fi
if [ "$DIFF_VERIFIED" = "true" ] && [ -n "${AGENT_EXPECTED_CHANGED_FILES:-}${AGENT_FORBIDDEN_CHANGED_FILES:-}" ]; then
echo "Diff verification passed (changed: $DIFF_SUMMARY)"
fi
else
echo "WARNING: /workspace/reference/main has no commits; skipping diff verification"
fi
else
echo "Note: /workspace/reference/main not present; skipping AR-21 diff verification"
# AGENT_SKIP_BRANCH_PUSH: direct-push agents (e.g. integrators) push to origin
# main themselves and don't want a task branch created as a side-effect.
if [ "$SKIP_BRANCH_PUSH" = "true" ]; then
echo "AGENT_SKIP_BRANCH_PUSH=true — skipping task branch push"
python3 -c "
import json, os
out = '$METADATA_FILE'
meta = {}
if os.path.isfile(out):
try:
with open(out) as f:
meta = json.load(f)
except Exception:
meta = {}
meta['agent_branch'] = '$BRANCH'
meta['agent_repo_url'] = '$REPO_URL'
meta['agent_branch_pushed'] = False
meta['direct_push_mode'] = True
with open(out, 'w') as f:
json.dump(meta, f)
print('Wrote ci_metadata.json (direct_push_mode: branch push skipped)')
"
echo "=== agent-repo/v1 finalize.sh complete (direct_push_mode) ==="
exit 0
fi
set -eo pipefail
# AR-19: Push with retry — attempt up to PUSH_RETRIES+1 times (default 2: initial + 1 retry)
echo "Pushing branch $BRANCH to $REPO_URL..."
@@ -344,23 +359,13 @@ for attempt in $(seq 1 $((PUSH_RETRIES + 1))); do
sleep 5
echo "Retry $attempt: git push $REPO_URL HEAD:refs/heads/$BRANCH --force"
fi
# Capture push output explicitly to stderr so it shows in finalize-error
# capture (the previous `if cmd 2>&1; then` form let git stderr go to
# stdout where it was lost — the actual push error message wasn't
# visible in CP logs, hiding e.g. "Permission denied (publickey)" or
# "remote: error: ..." rejections. Real incident: 2026-05-08 probe 6
# silently failed for 6 retries with no visible reason.
set +e
PUSH_OUT=$(timeout 120 git push "$REPO_URL" "HEAD:refs/heads/$BRANCH" --force 2>&1)
PUSH_EXIT=$?
set -e
echo "git push attempt $attempt exit=$PUSH_EXIT, output:" >&2
echo "$PUSH_OUT" >&2
if [ "$PUSH_EXIT" -eq 0 ]; then
if timeout 120 git push "$REPO_URL" "HEAD:refs/heads/$BRANCH" --force 2>&1; then
echo "Push succeeded (attempt $attempt)"
PUSHED=true
PUSH_EXIT=0
break
else
PUSH_EXIT=$?
echo "Push attempt $attempt failed with exit code $PUSH_EXIT"
if [ "$attempt" -lt $((PUSH_RETRIES + 1)) ]; then
echo "Will retry..."
@@ -395,28 +400,30 @@ meta['diff_kb'] = float('$DIFF_KB') if '$DIFF_KB' else 0.0
meta['output_validated'] = $( [ '$OUTPUT_VALIDATED' = 'true' ] && echo 'True' || echo 'False' )
if '$OUTPUT_MISSING':
meta['output_missing'] = '$OUTPUT_MISSING'
# AR-21: diff verification metadata
meta['diff_verified'] = $( [ '$DIFF_VERIFIED' = 'true' ] && echo 'True' || echo 'False' )
if '$DIFF_MISMATCH'.strip():
meta['diff_mismatch'] = '$DIFF_MISMATCH'.strip()
if '$DIFF_SUMMARY':
meta['diff_changed_files'] = [f for f in '$DIFF_SUMMARY'.split(',') if f]
# AR-38 / F97: record empty-deliverable audit outcome.
# Only emit the key when the audit ran. Skipped state omits the key so that
# downstream consumers can tell apart ran-and-passed from did-not-run.
ed = '$EMPTY_DELIVERABLE'
if ed == 'true':
meta['empty_deliverable'] = True
elif ed == 'false':
meta['empty_deliverable'] = False
with open(out, 'w') as f:
json.dump(meta, f)
print('Wrote ci_metadata.json')
"
# AR-38 / F97: exit non-zero (dedicated code 2) when audit flagged the commit.
# Take precedence over push failure (code 1) — empty deliverable is the more
# actionable signal for the operator. Exit only after push attempt above so
# the commit is still pushed for forensics.
if [ "$EMPTY_DELIVERABLE" = "true" ]; then
echo "ERROR: exiting 2 — AR-38 empty-deliverable audit failed" >&2
exit 2
fi
if [ "$PUSHED" = "false" ]; then
exit 1
fi
# AR-21: fail the task if diff verification didn't pass — even if push succeeded.
# Branch is preserved on the agent repo for forensics, but the task ends as
# failed so the operator + CP know it shouldn't be merged.
if [ "$DIFF_VERIFIED" = "false" ]; then
echo "ERROR: Diff verification failed:$DIFF_MISMATCH" >&2
echo "Branch $BRANCH is pushed for forensics, but the task is being marked failed." >&2
exit 1
fi
echo "=== agent-repo/v1 finalize.sh complete ==="