sac-interaction-b3eb70 — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sac-interaction-b3eb70 (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use SaC when Codex should present complex engineering analysis as an interactive app instead of a long markdown answer. The best Codex/SaC demos are developer workbenches: repo architecture maps, release readiness dashboards, PR/CI triage, migration plans, logs, test failures, and risk reviews.
Do not use SaC for short answers, simple code edits, or ordinary chat.
SaC server lifecycle is not your responsibility. You are a publish client, not an operator. Do not:
engineering analysis or code changes
If /inbox is unreachable (connection refused), follow this diagnostic sequence:
Step 1 — Connectivity check. Run a lightweight health probe first:
curl -sS --connect-timeout 5 http://127.0.0.1:18420/healthIf this returns {"status":"ok"}, the server IS running and curl GET works. The POST failure is likely caused by payload construction, shell quoting, --data-binary @- piping, or a POST-specific environment restriction. Skip to Step 3 to use a more robust transport.
If this also fails (connection refused), the server is truly down. Continue to Step 2.
Step 2 — Start the server. Run sac serve exactly once:
sac servesac serve is idempotent and safe to run even if a server is already running — it reuses a healthy one and exits, and refuses to fight a contended port instead of producing a half-bound zombie. After sac serve, retry the same POST with curl. If the retry succeeds, you are done.
Step 3 — Python fallback. If curl POST still fails but the health check passed (or sac serve reported "already running and healthy"), use Python urllib as an alternative transport. Write the full JSON payload to a temporary file first so large markdown content with quotes, backticks, and newlines is never shell-escaped:
python3 -c "
import urllib.request, json, os, sys
payload = json.dumps({
'content': 'CONTENT',
'intent': 'INTENT',
'callback_url': f'codex://resume?thread=last&cwd={os.getcwd()}',
'callback_format': 'codex_exec_resume',
})
req = urllib.request.Request('http://127.0.0.1:18420/inbox',
data=payload.encode(), headers={'Content-Type': 'application/json'})
resp = urllib.request.urlopen(req, timeout=300)
print(resp.read().decode())
"Replace CONTENT and INTENT with actual values.
If both curl and Python fallback fail, tell the user exactly: "SaC server unavailable — start it with `sac serve`." Then stop. Do not improvise.
SaC runs locally at http://127.0.0.1:18420. Use that URL.
Fast path: do not over-investigate. Gather only the minimal context needed to compose a useful workbench, then publish. Honor the infrastructure boundary above — composing and POSTing content is the whole job.
Compose substantive markdown content first. Prefer structured sections, tables, risks, decisions, and next actions.
Publish in exactly one POST. Do not send a smoke / probe / draft POST to "test the endpoint" before the real content: the first POST becomes app v1, so a throwaway draft pollutes the version history and doubles the render cost. The /inbox endpoint is reliable — compose the complete content, then POST it once. (sac serve health is already covered by the infrastructure boundary above; do not re-verify with a tiny POST.)
Publish using the sac publish CLI. Write the content to a temp file first — this avoids all shell-escaping issues with backticks, quotes, and newlines in large markdown payloads:
cat > /tmp/sac_content.md << 'CONTENT_EOF'
CONTENT
CONTENT_EOF
sac publish --file /tmp/sac_content.md \
--intent "INTENT" \
--callback-url "codex://resume?thread=last&cwd=$(pwd)" \
--callback-format codex_exec_resumeReplace CONTENT inside the heredoc with the actual markdown analysis, and INTENT with a short description (e.g. SaC SDK release readiness dashboard). The heredoc (<< 'CONTENT_EOF') prevents shell expansion.
Fields:
--file: path to the content file.--intent: short description of the content.--callback-url: tells SaC how to send app button clicks back to Codex.thread=last: safe bootstrap default. SaC auto-pins the concretethread id after the first callback (it reads thread.started from the Codex stream and rewrites the stored callback_url), so every subsequent user action resumes this exact thread. The only residual race is if another Codex session starts between publish and the first click; if you already know your thread id, pass it explicitly as thread=<id> to close even that window.
cwd=$(pwd): resume Codex in your current working directory. The $(pwd) is expanded by the shell so Codex callbacks always return to the right project.sac publish prints the app URL to stdout. Always show it to the user.
Keep the conversation_id (printed to stderr) for updates.
Fallback: if sac publish is not on PATH, use curl:
curl -s --connect-timeout 5 -X POST "http://127.0.0.1:18420/inbox" \
-H "Content-Type: application/json" \
-d "{\"content\": \"CONTENT\", \"intent\": \"INTENT\", \"callback_url\": \"codex://resume?thread=last&cwd=$(pwd)\", \"callback_format\": \"codex_exec_resume\"}"For follow-up changes, publish updated content with the existing conversation_id:
sac publish --file /tmp/sac_updated.md \
--conversation-id "abc-123" \
--intent "what changed"Or with curl:
curl -s --connect-timeout 5 -X POST "http://127.0.0.1:18420/inbox" \
-H "Content-Type: application/json" \
-d '{"conversation_id": "abc-123", "content": "UPDATED CONTENT", "intent": "what changed"}'When the user's action is conversational — a greeting, question, clarification, or small talk — do not evolve the app. Instead, POST a chat message:
cat > /tmp/sac_chat.json << 'CHAT_EOF'
{"conversation_id": "abc-123", "content": "YOUR_REPLY", "type": "chat"}
CHAT_EOF
curl -s --connect-timeout 5 -X POST "http://127.0.0.1:18420/inbox" \
-H "Content-Type: application/json" \
--data-binary @/tmp/sac_chat.jsonThis shows an assistant bubble in the viewer without touching the app UI.
When a user clicks a button or sends a message in the SaC app, SaC resumes Codex with a message that starts:
A user is viewing a SaC interactive app and requested: ...Follow that message exactly:
or a chat reply (greeting, question, explanation)?
"Update Existing App" above) with the same conversation_id.
action explicitly asks for it.
content and intent should describe WHAT to show — do NOT includeUI styling directions (colors, dark/light theme, CSS classes, layout instructions). SaC controls visual design autonomously.
Use this as the primary B2D validation scenario:
Analyze this SaC SDK and create an interactive release readiness dashboard using SaC.The first app should include:
Inspect Codex integration path, Show release blockers, and Drill into callback adaptersButtons that need follow-up analysis should call:
window.__sac_action("Inspect Codex integration path", {
action_id: "inspect_codex_integration",
target: { type: "integration", id: "codex" }
})~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.