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:
29
harnesses/contexts/z-ai/v1/harness.yaml
Normal file
29
harnesses/contexts/z-ai/v1/harness.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
kind: context
|
||||
name: z-ai
|
||||
version: 1
|
||||
description: "Z.ai — Anthropic-API-compatible endpoint"
|
||||
requires: []
|
||||
provides: [claude-code]
|
||||
|
||||
# Auth is wired by init.sh via Claude Code's apiKeyHelper (settings.json).
|
||||
# No credential env vars: the secret stays in the mounted file and is read
|
||||
# only by the helper command at request time.
|
||||
env:
|
||||
ANTHROPIC_BASE_URL: "https://api.z.ai/v1"
|
||||
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: "1"
|
||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1"
|
||||
DISABLE_PROMPT_CACHING: "1"
|
||||
|
||||
secrets_required:
|
||||
- name: z-ai
|
||||
account_ref: "z-ai"
|
||||
mount_path: /run/agent/secrets/z-ai
|
||||
# 0400 (root-only) — defense in depth. The agent user CANNOT read this
|
||||
# mount. init.sh runs as root and `install`s a per-secret copy into the
|
||||
# agent's home with mode 0600 owned by agent; only that copy is exposed
|
||||
# to the runtime. Matches the gitea-ssh pattern. If the ESO Secret
|
||||
# later grows additional keys, they remain inaccessible by default.
|
||||
mode: "0400"
|
||||
|
||||
scripts:
|
||||
init: ./init.sh
|
||||
76
harnesses/contexts/z-ai/v1/init.sh
Executable file
76
harnesses/contexts/z-ai/v1/init.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
# z-ai init — stage the auth_token for the agent user and wire apiKeyHelper.
|
||||
#
|
||||
# Threat model: keep the ESO mount root-only (mode 0400) so the agent user
|
||||
# cannot directly `cat` /run/agent/secrets/z-ai/auth_token. init.sh runs as
|
||||
# root (in uid-wrapper.sh, before the gosu drop) and stages a per-secret
|
||||
# copy into the agent's home with mode 0600 owned by agent. apiKeyHelper
|
||||
# points at the COPY. This is the gitea-ssh pattern — only the file the
|
||||
# harness explicitly grants is reachable by the runtime.
|
||||
#
|
||||
# Rotation handling: this is a one-shot copy at container start. For
|
||||
# ephemeral container agents (one task = one container) every task starts
|
||||
# with the latest secret. Long-running sessions don't refresh the copy
|
||||
# until a future scripts.control_loop hook lands (planning E1-M3).
|
||||
#
|
||||
# Auth wire-up: apiKeyHelper output is sent as `Authorization: Bearer
|
||||
# <value>` when ANTHROPIC_BASE_URL is non-anthropic.com — exactly what
|
||||
# api.z.ai/v1 requires. The secret value never enters this process' env,
|
||||
# the claude subprocess' env, or /proc/<pid>/environ.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ESO_AUTH_TOKEN="/run/agent/secrets/z-ai/auth_token"
|
||||
|
||||
if [ ! -r "$ESO_AUTH_TOKEN" ]; then
|
||||
echo "ERROR: $ESO_AUTH_TOKEN not readable. Check ESO ExternalSecret acct-<z-ai-id>." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Resolve the agent user's home (init.sh's $HOME is /root before gosu drop).
|
||||
AGENT_USER="${AGENT_USER:-agent}"
|
||||
AGENT_HOME=$(getent passwd "$AGENT_USER" | cut -d: -f6)
|
||||
if [ -z "$AGENT_HOME" ] || [ ! -d "$AGENT_HOME" ]; then
|
||||
AGENT_HOME="/home/$AGENT_USER"
|
||||
fi
|
||||
|
||||
# Stage the auth_token into a per-secret path owned by agent, mode 0600.
|
||||
# install(1) handles ownership/mode atomically; the destination is outside
|
||||
# the read-only ESO mount so we can chmod/chown freely.
|
||||
STAGED_KEY_DIR="$AGENT_HOME/.claude/secrets"
|
||||
STAGED_KEY="$STAGED_KEY_DIR/z-ai-token"
|
||||
mkdir -p "$STAGED_KEY_DIR"
|
||||
chown "$AGENT_USER:" "$STAGED_KEY_DIR" 2>/dev/null || true
|
||||
chmod 0700 "$STAGED_KEY_DIR"
|
||||
install -m 0600 -o "$AGENT_USER" -g "$AGENT_USER" "$ESO_AUTH_TOKEN" "$STAGED_KEY"
|
||||
|
||||
# Wire apiKeyHelper to the staged copy in the agent's settings.json.
|
||||
CONFIG_DIR="${CLAUDE_CONFIG_DIR:-$AGENT_HOME/.claude}"
|
||||
mkdir -p "$CONFIG_DIR"
|
||||
chown "$AGENT_USER:" "$CONFIG_DIR" 2>/dev/null || true
|
||||
chmod 0755 "$CONFIG_DIR"
|
||||
|
||||
SETTINGS_FILE="$CONFIG_DIR/settings.json"
|
||||
|
||||
# Merge into an existing settings.json (from another harness layer) when
|
||||
# possible; otherwise create a fresh one.
|
||||
if [ -f "$SETTINGS_FILE" ] && command -v jq >/dev/null 2>&1; then
|
||||
TMP=$(mktemp)
|
||||
jq --arg helper "cat $STAGED_KEY" \
|
||||
'. + {apiKeyHelper: $helper}' \
|
||||
"$SETTINGS_FILE" > "$TMP"
|
||||
mv "$TMP" "$SETTINGS_FILE"
|
||||
else
|
||||
cat > "$SETTINGS_FILE" <<EOF
|
||||
{
|
||||
"apiKeyHelper": "cat $STAGED_KEY"
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# settings.json holds a command (a path), not a credential value.
|
||||
chown "$AGENT_USER:" "$SETTINGS_FILE" 2>/dev/null || true
|
||||
chmod 0644 "$SETTINGS_FILE"
|
||||
|
||||
echo "z-ai auth_token staged at $STAGED_KEY (0600 $AGENT_USER:$AGENT_USER)"
|
||||
echo "z-ai apiKeyHelper wired in $SETTINGS_FILE"
|
||||
Reference in New Issue
Block a user