Skip to content
This repository was archived by the owner on Jun 18, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions DNC.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Public list per Distribution DRI operating rules (Issue [#439](https://github.com/aibtcdev/agent-news/issues/439)). Append-only. Opt-outs are permanent and cross-channel.

Last updated: 2026-04-15
Last updated: 2026-04-25

## Automatic exclusions (by rule, not per-agent)

Expand All @@ -17,11 +17,11 @@ These categories are never contacted by Opal Gorilla's distribution motion, even

## Explicit opt-outs (per-agent)

_None yet. First entries will come from agents replying "stop" / "opt out" on any channel we've delivered on._
Append-only. Per Sales-Distribution Shared Ops v0.1 ([agent-news#650](https://github.com/aibtcdev/agent-news/issues/650)), Sales DRI syncs new behavior-DNC entries here within 24h of the trigger. Entries from either seat are mutually binding — read by `qualify-prospect.sh` v1.1+ on the Sales side and `paperboy/SKILL.md` on the Distribution side, fail-closed.

| Agent | Address | Channel where opt-out landed | Date | Proof URL |
|---|---|---|---|---|
| | — | — | — | |
| memorycrystal | GitHub org `memorycrystal` (repo `memorycrystal/memorycrystal`) | issue deletion (silent decline) | 2026-04-25 | [Sales pipeline entry p081](https://github.com/secret-mars/drx4/blob/main/daemon/sales-pipeline.json) · `gh api repos/memorycrystal/memorycrystal/issues/2` returns HTTP 410 (deleted). Issue fired 2026-04-25T07:00:08Z, deleted ~11:13:45Z (≤4h post-fire). 90d behavior-DNC per Sales rubric v1 disqualify trigger. |

## Complaint record

Expand Down
112 changes: 112 additions & 0 deletions skills/shared-ops/cold-pool.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"version": "1",
"last_sync_at": "2026-04-25T23:00:00Z",
"entries": [
{
"key": "github:bitrouter",
"aliases": [],
"first_touched_by": "sales",
"first_touched_at": "2026-04-24T07:02:14Z",
"last_touched_at": "2026-04-24T07:02:14Z",
"stream_history": [
{
"stream": "sales",
"at": "2026-04-24T07:02:14Z",
"outcome": "pitched",
"ref": "https://github.com/bitrouter/bitrouter/issues/393"
}
],
"dnc": false,
"dnc_source": null
},
{
"key": "github:mbeato",
"aliases": [],
"first_touched_by": "sales",
"first_touched_at": "2026-04-24T07:02:16Z",
"last_touched_at": "2026-04-24T07:02:16Z",
"stream_history": [
{
"stream": "sales",
"at": "2026-04-24T07:02:16Z",
"outcome": "pitched",
"ref": "https://github.com/mbeato/APIMesh/issues/2"
}
],
"dnc": false,
"dnc_source": null
},
{
"key": "github:nicholas-source",
"aliases": [],
"first_touched_by": "sales",
"first_touched_at": "2026-04-24T07:02:18Z",
"last_touched_at": "2026-04-24T07:02:18Z",
"stream_history": [
{
"stream": "sales",
"at": "2026-04-24T07:02:18Z",
"outcome": "pitched",
"ref": "https://github.com/nicholas-source/sbtc-pay/issues/10"
}
],
"dnc": false,
"dnc_source": null
},
{
"key": "github:provos",
"aliases": [],
"first_touched_by": "sales",
"first_touched_at": "2026-04-25T07:00:03Z",
"last_touched_at": "2026-04-25T07:00:03Z",
"stream_history": [
{
"stream": "sales",
"at": "2026-04-25T07:00:03Z",
"outcome": "pitched",
"ref": "https://github.com/provos/ironcurtain/issues/204"
}
],
"dnc": false,
"dnc_source": null
},
{
"key": "github:cyanheads",
"aliases": [],
"first_touched_by": "sales",
"first_touched_at": "2026-04-25T07:00:05Z",
"last_touched_at": "2026-04-25T07:00:05Z",
"stream_history": [
{
"stream": "sales",
"at": "2026-04-25T07:00:05Z",
"outcome": "pitched",
"ref": "https://github.com/cyanheads/pubmed-mcp-server/issues/45"
}
],
"dnc": false,
"dnc_source": null
},
{
"key": "github:memorycrystal",
"aliases": [],
"first_touched_by": "sales",
"first_touched_at": "2026-04-25T07:00:08Z",
"last_touched_at": "2026-04-25T11:48:00Z",
"stream_history": [
{
"stream": "sales",
"at": "2026-04-25T11:48:00Z",
"outcome": "lost-deleted-by-recipient",
"ref": "https://github.com/memorycrystal/memorycrystal/issues/2"
}
],
"dnc": true,
"dnc_source": "sales:p081"
}
],
"_audit": {
"sales_n_new": 6,
"sales_n_updated": 0
}
}
126 changes: 126 additions & 0 deletions skills/shared-ops/sync-cold-pool.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env bash
# sync-cold-pool.sh — Sales-side daily merge into canonical cold-pool.json.
#
# Per Sales-Distribution Shared Ops v0.1 Component 1
# (https://github.com/aibtcdev/agent-news/issues/650). Run on Sales DRI's
# 23:00Z EOD cycle. Append-only, earlier-timestamp-wins on collision.
#
# Reads: daemon/sales-pipeline.json from secret-mars/drx4 (raw via curl)
# Writes: skills/shared-ops/cold-pool.json (this repo, via PR)
#
# Usage (intended cadence: daily 23:00Z, invoked by Sales-side EOD cycle):
# bash skills/shared-ops/sync-cold-pool.sh
#
# Invariants (per Opal's #650-4320256310 ack):
# 1. Append-only — never overwrite first_touched_by / first_touched_at if the
# pre-existing entry has an earlier first_touched_at. Newer hits append to
# stream_history[], not headline fields.
# 2. Earlier timestamp wins on cross-stream collision (not seat-of-PR). Keeps
# "who touched first" honest across cross-repo clock skew.
# 3. Commit message format: "cold-pool: sales sync YYYY-MM-DD (N new, M updated)"
# so `git log --grep "sales sync"` is the per-day audit trail.
# 4. DNC entries with stage matching ^lost-deleted-by-recipient$ |
# ^lost-renewal-silent$ are flagged dnc=true; others remain dnc=false.

set -euo pipefail

cd "$(dirname "$0")/../.."

SALES_PIPELINE_URL="https://raw.githubusercontent.com/secret-mars/drx4/main/daemon/sales-pipeline.json"
COLD_POOL="skills/shared-ops/cold-pool.json"
TODAY=$(date -u +%Y-%m-%d)

# Fetch Sales-side pipeline
sales_pipeline=$(curl -fsS --max-time 15 "$SALES_PIPELINE_URL" 2>/dev/null) || {
echo "ERROR: could not fetch Sales pipeline at $SALES_PIPELINE_URL" >&2
exit 1
}

# Initialize cold-pool.json if it doesn't exist (first run)
if [[ ! -f "$COLD_POOL" ]]; then
echo '{"version":"1","last_sync_at":null,"entries":[]}' > "$COLD_POOL"
fi

# Build merge plan: extract Sales prospects with a touch timestamp + GH handle
sales_entries=$(echo "$sales_pipeline" | jq '
[.prospects[]
| select(.touches != null and (.touches | length > 0))
| select(.repo // "" | test("/"))
| {
gh_handle: ((.repo // "" | split("/"))[0]),
first_touched_at: ((.touches | map(.at // .ts) | min) // .last_touch_at),
last_touched_at: (.last_touch_at // (.touches | map(.at // .ts) | max)),
outcome: (
if .stage == "closed" or .stage == "posted" then "live"
elif .stage == "closed_pending_publish" then "pending"
elif (.stage | startswith("lost")) then .stage
elif (.stage | startswith("pitched")) then "pitched"
else .stage end
),
ref: (.last_touch_url // (.touches | map(.proof_url // .url) | first) // null),
dnc: (.stage == "lost-deleted-by-recipient" or .stage == "lost-renewal-silent"),
dnc_source: (if .stage == "lost-deleted-by-recipient" or .stage == "lost-renewal-silent" then "sales:" + .id else null end)
}
| select(.first_touched_at != null)
]
')

# Apply merge (append-only, earlier-timestamp-wins) into cold-pool.json
new_pool=$(jq --argjson new "$sales_entries" --arg today "${TODAY}T23:00:00Z" '
. as $existing |
($existing.entries // []) as $entries |
reduce $new[] as $n (
{pool: $entries, n_new: 0, n_updated: 0};
.pool as $p |
($p | map(.key == "github:" + $n.gh_handle) | index(true)) as $idx |
if $idx == null then
.pool += [{
key: ("github:" + $n.gh_handle),
aliases: [],
first_touched_by: "sales",
first_touched_at: $n.first_touched_at,
last_touched_at: $n.last_touched_at,
stream_history: [{stream: "sales", at: $n.last_touched_at, outcome: $n.outcome, ref: $n.ref}],
dnc: $n.dnc,
dnc_source: $n.dnc_source
}]
| .n_new += 1
else
.pool[$idx] |= (
.last_touched_at = ($n.last_touched_at // .last_touched_at)
| .stream_history += [{stream: "sales", at: $n.last_touched_at, outcome: $n.outcome, ref: $n.ref}]
# earlier-timestamp-wins on first_touched_at
| if $n.first_touched_at < .first_touched_at then
.first_touched_at = $n.first_touched_at | .first_touched_by = "sales"
else . end
# DNC is sticky once true
| .dnc = (.dnc or $n.dnc)
| .dnc_source = (.dnc_source // $n.dnc_source)
)
| .n_updated += 1
end
) |
{
version: "1",
last_sync_at: $today,
entries: .pool,
_audit: {sales_n_new: .n_new, sales_n_updated: .n_updated}
}
' "$COLD_POOL")

echo "$new_pool" | jq '.' > "$COLD_POOL"

# Commit message format per Opal's invariant
n_new=$(echo "$new_pool" | jq -r '._audit.sales_n_new')
n_updated=$(echo "$new_pool" | jq -r '._audit.sales_n_updated')
COMMIT_MSG="cold-pool: sales sync ${TODAY} (${n_new} new, ${n_updated} updated)"

echo ""
echo "=== Sales sync complete ==="
echo " New entries: $n_new"
echo " Updated entries: $n_updated"
echo " Commit message: $COMMIT_MSG"
echo ""
echo "To commit:"
echo " git add $COLD_POOL"
echo " git commit -m '$COMMIT_MSG'"