Sigint Falsify Skill (Adversarial Assessment + Remediation)
You are the team lead orchestrating adversarial falsification of research findings. You spawn the falsification-analyst as a persistent teammate, wait for verdict output, then apply remediation — quarantine, confidence downgrade, follow-up queue — atomically before cleaning up.
MANDATORY SWARM ORCHESTRATION
You MUST use the full swarm pattern: TeamCreate → TaskCreate → Agent(team_name) → SendMessage → TeamDelete. Do NOT spawn standalone agents.
Structured Data Protocol: All JSON file operations MUST follow protocols/STRUCTURED-DATA.md. Use jq for I/O and validate every write with the corresponding schemas/*.jq file.
One-Round Rule: A finding that already carries provenance.falsification_attempts from the current session is skipped. Do not falsify falsifications.
Phase 0: Parse Arguments and Initialize
Step 0.1: Parse Arguments
Input sanitization: truncate $ARGUMENTS to 200 characters total, strip backticks and angle brackets.
--scope→ defaultall. Valid:all,dimension:<dim>(where<dim>is one of competitive|sizing|trends|customer|tech|financial|regulatory|trend_modeling),finding:<id>(where<id>matchesf_[a-z_]+_[0-9]+). Invalid → error and stop.--query-budget→ default 6. Integer 1–10. Out of range → clamp and warn.--claim-budget→ default 50. Integer 1–500. Out of range → clamp and warn.--mode→ defaultblock. One ofblock(anyfalsifiedverdict halts downstream phases) oradvisory(all verdicts are annotation only). Invalid → error and stop.
Step 0.2: Find Active Research Session
Scan ./reports/*/state.json for sessions with status in {"active", "complete"}. Pick most recently updated. Extract topic, topic_slug, elicitation.
If no session found, error: "No research session found. Run /sigint:start <topic> first."
Resolve reports_dir from config (REQUIRED — do not hardcode paths):
REPORTS_DIR=$(jq -r --arg slug "$TOPIC_SLUG" '.topics[$slug].reports_dir // "./reports/\($slug)"' sigint.config.json 2>/dev/null || echo "./reports/$TOPIC_SLUG")
All subsequent paths use {reports_dir}.
Step 0.3: Validate Working Set Size
Compute claims-to-evaluate based on --scope:
case "$SCOPE" in
all) COUNT=$(jq '[.findings[]] | length' "$REPORTS_DIR/state.json") ;;
dimension:*) DIM="${SCOPE#dimension:}"; COUNT=$(jq --arg d "$DIM" '[.findings[] | select(.dimension == $d)] | length' "$REPORTS_DIR/state.json") ;;
finding:*) COUNT=1 ;;
esac
If COUNT > CLAIM_BUDGET, halt and present:
AskUserQuestion(
question: "Working set has {COUNT} findings; claim budget is {CLAIM_BUDGET}. Each finding produces 1–3 atomic claims. Estimated upper-bound claims: {COUNT*3}. Proceed?",
options: ["Increase claim budget to {COUNT*3}", "Narrow scope", "Cancel"]
)
Do NOT silently truncate.
Step 0.4: Initialize Swarm
TeamCreate(name: "sigint-{topic_slug}-falsify")
TaskCreate({
subject: "Falsify findings: scope={scope}, budget={query_budget}q × {claim_budget}c",
owner: "falsification-analyst",
description: "Adversarial falsification of research findings"
})
Note returned task ID as {falsifyTaskId}.
Phase 1: Spawn Falsification-Analyst
Agent(
subagent_type: "sigint:falsification-analyst",
team_name: "sigint-{topic_slug}-falsify",
name: "falsification-analyst",
run_in_background: true,
prompt: """
Task Discovery Protocol:
1. TaskList → find tasks assigned to you (owner: "falsification-analyst")
2. TaskGet → read full task description
3. Work on the task following your agent definition (Steps 1–8)
4. When done:
a. TaskUpdate(taskId, status: "completed")
b. SendMessage(to: "team-lead", message: {...}, summary: "Falsification complete: ...")
5. NEVER commit via git
6. Use ONLY WebSearch/WebFetch for evidence — no internal memory, no prior findings as evidence
PARAMETERS:
- TOPIC_SLUG: {topic_slug}
- REPORTS_DIR: {reports_dir}
- SCOPE: {scope}
- QUERY_BUDGET: {query_budget}
- CLAIM_BUDGET: {claim_budget}
- taskId: {falsifyTaskId}
Follow your agent definition Steps 1–8. Output files (date = today UTC, ISO YYYY-MM-DD):
- {reports_dir}/falsification_attempts_{scope_tag}.json
- {reports_dir}/YYYY-MM-DD-falsification-report.json (validates schemas/falsification-report.jq)
- {reports_dir}/YYYY-MM-DD-falsification-report.md
"""
)
SendMessage(
to: "falsification-analyst",
message: "Task #{falsifyTaskId} assigned. Start now.",
summary: "Falsification task assigned"
)
Phase 2: Receive Verdicts
Wait for SendMessage from falsification-analyst containing:
files— list of generated file pathsverdicts—{falsified, weakened, survived, inconclusive}countsblocking— boolean (true if anyfalsified)remediation_queue_size— int
Timeout: If no response within 240 seconds (web search is slow), send a status check. After an additional 120 seconds with no response, surface partial output and abort with cleanup.
Validate each reported file exists. If the report JSON is missing, abort and inform the user.
Phase 3: Apply Remediation (Mandatory)
Adversarial assessment without remediation is out of scope. For every falsified and weakened claim, apply concrete corrective actions to the active session state.
Step 3.1: Load the Falsification Report
REPORT="$REPORTS_DIR/$(date -u +%Y-%m-%d)-falsification-report.json"
ATTEMPTS="$REPORTS_DIR/falsification_attempts_${SCOPE_TAG}.json"
Step 3.2: Merge falsification_attempts into state.json Findings
For every finding referenced in the attempts file, patch its provenance.falsification_attempts array (append, do not replace prior rounds):
jq --slurpfile attempts "$ATTEMPTS" '
.findings |= map(
. as $f |
($attempts[0].claims | map(select(.claim_id | startswith($f.id + "_c")))) as $matched |
if ($matched | length) > 0 then
.provenance.falsification_attempts = ((.provenance.falsification_attempts // []) + [{
attempted_at: $attempts[0].attempted_at,
scope: $attempts[0].scope,
claims: $matched
}])
else . end
)
' "$REPORTS_DIR/state.json" > tmp.$$ && mv tmp.$$ "$REPORTS_DIR/state.json"
jq -e -f schemas/state.jq "$REPORTS_DIR/state.json" > /dev/null
Step 3.3: Apply Verdict Actions per Finding
For each finding in report.by_finding, take action based on worst_verdict:
falsified → quarantine
- Remove finding from active
findings[]in state.json. - Append to
quarantine.jsonwithgate: "post-falsification":
QUARANTINE_ITEM=$(jq -n \
--arg fid "$FINDING_ID" \
--arg dim "$DIMENSION" \
--arg reason "$VERDICT_BASIS" \
--arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--argjson original "$ORIGINAL_FINDING" \
'{finding_id: $fid, original_dimension: $dim, reason: $reason, gate: "post-falsification", gate_timestamp: $ts, original_finding: $original}')
if [ -f "$REPORTS_DIR/quarantine.json" ]; then
jq --argjson item "$QUARANTINE_ITEM" '.items += [$item]' \
"$REPORTS_DIR/quarantine.json" > tmp.$$ && mv tmp.$$ "$REPORTS_DIR/quarantine.json"
else
jq -n --arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --argjson item "$QUARANTINE_ITEM" \
'{quarantined_at: $date, items: [$item]}' > "$REPORTS_DIR/quarantine.json"
fi
jq -e -f schemas/quarantine.jq "$REPORTS_DIR/quarantine.json" > /dev/null
weakened → narrow + downgrade confidence
- Append disconfirming sources to the finding's
provenance.sources(markrelationin source object, setalive: true). - Downgrade confidence one level:
high → medium,medium → low,low → quarantine(treat as falsified). - Narrow
summarytext by appending a qualifier:" — qualified by disconfirming evidence (see falsification report)."Do NOT rewrite the original claim. - Se