assistant-claw/state-schemas/customer.md
Atlas refactor bd0be97630 Refactor: drop Vega framing, promote Atlas to repo root
This repo IS Atlas (总助 Claw / 老板视角项目执行雷达). The earlier
two-profile framing (Atlas + Vega placeholder) was a misread — Vega is
the agent persona answering Multica issues, not the product. Vega has
no relationship to assistant-claw the product.

Changes:
- Move atlas/* to top-level (git mv preserves history)
- Remove empty Vega placeholders prompts/.gitkeep, tools/.gitkeep
- Delete atlas/ wrapper directory (now empty)
- Update path references in INTEGRATION-hermes.md, scripts/mirror-...sh,
  docs/decisions/0001-mirror-nuwa-skill.md
- Rewrite README.md as Atlas-only, remove dual-profile language

After this commit:
- Top-level OpenClaw 8 files (IDENTITY/SOUL/USER/AGENTS/TOOLS/MEMORY/
  BOOTSTRAP/HEARTBEAT + CLAUDE symlink + zh-CN mirrors)
- skills/{6 sub-skills + DESCRIPTION + README}
- mcp-tools/{spec + Python implementation}
- state-schemas/{project, person, customer + README}
- autopilots/{5 atlas-*.yaml}
- client-deck/, docs/decisions/, scripts/

The ~/.hermes/skills/atlas/ destination convention preserved (atlas as
a skill namespace on the operator's machine, distinct from source path).
2026-05-09 17:54:18 +08:00

7.1 KiB
Raw Permalink Blame History

State Schema: state/customers/CUST-*.json

Owned by: claw-customer-radar (write); read by claw-report-writer.

Identifier convention

CUST-<slug> where slug is derived from the primary email domain or the boss-confirmed customer name.

Examples: CUST-clientco, CUST-customer-A, CUST-momo-tech

Unconfirmed candidate customers are stored as UNCLASSIFIED-<domain>.json and surface in W1 audit for boss to confirm/merge.

Top-level shape

{
  "id": "CUST-clientco",                              // string
  "name": "客户A",                                     // string, boss-confirmed display name
  "domains": ["clientco.com", "client-co.cn"],         // array<string>, all email domains for this customer
  "lifecycle_stage": "At-Risk",                       // enum: Lead | Onboarding | Active | At-Risk | Churned

  "关联项目": [                                        // array<object>
    {
      "id": "PRJ-2025-001-客户A官网改版",
      "状态": "Stalled",
      "金额": 120000
    },
    {
      "id": "PRJ-2026-014-customer-A-supply",
      "状态": "Active",
      "金额": 80000
    }
  ],

  "健康度": {                                         // object — Customer Health Score
    "score": 62,                                       // int 0..100
    "档位": "黄(注意)",                              // enum: 绿(健康) | 黄(注意) | 红(危急)
    "构成": {                                          // object, weighted components
      "项目健康": 0.60,                                // float, weight 0.4
      "情绪趋势_30d": -0.5,                            // float, weight 0.3
      "邮件频率_normalcy": 1.0,                        // float, weight 0.2
      "金额规模_normalized": 0.7                       // float, weight 0.1
    },
    "computed_at": "2026-05-09T07:30:00Z",
    "previous_tier": "绿(健康)",                     // for Andon detection
    "tier_change_at": "2026-05-08T07:30:00Z"
  },

  "情绪趋势_90d": [                                   // array<object>, monthly buckets
    {"month": "2026-02", "score": 0.7, "代表词": "期待 / 配合", "n_quotes": 12},
    {"month": "2026-03", "score": 0.5, "代表词": "等候 / 询问", "n_quotes": 9},
    {"month": "2026-04", "score": 0.2, "代表词": "催 / 失望", "n_quotes": 14}
  ],

  "RFM": {                                            // object
    "Recency": "5d",                                   // string, time since last interaction
    "Recency_iso": "2026-05-04T16:32:00Z",             // ISO timestamp for sorting
    "Frequency_30d": 14,                               // int, message count last 30d
    "Frequency_90d_baseline": 38,                      // int, baseline for normalcy comparison
    "Monetary": 200000                                 // number, sum of associated project amounts
  },

  "我方接口人": [                                      // array<object>, internal people who touch this customer
    {"name": "张三", "角色": "项目经理", "可靠度": "中", "primary_for_projects": ["PRJ-2025-001"]},
    {"name": "李四", "角色": "客户总监", "可靠度": "高", "primary_for_projects": ["PRJ-2026-014"]}
  ],

  "客户方决策链": [                                    // array<object>, external people on customer side
    {
      "name": "客户A-王总",
      "email": "wang@clientco.com",
      "角色": "决策者",                                // enum: 决策者 | 执行接口 | 用户 | 阻拦者
      "态度": "中性偏冷",
      "last_intervention": "2026-04-22"
    },
    {
      "name": "客户A-赵经理",
      "email": "zhao@clientco.com",
      "角色": "执行接口",
      "态度": "积极",
      "last_intervention": "2026-05-04"
    }
  ],

  "VoC_关键原话_30d": [                               // array<object>, max 5
    {
      "date": "2026-04-22",
      "speaker": "王总",
      "speaker_email": "wang@clientco.com",
      "原文": "再这样我就找别家了",
      "性质": "强负向",                                // enum: 强正向 | 正向 | 中性 | 负向 | 强负向
      "source_email_id": "msg-xyz@..."
    },
    {
      "date": "2026-04-15",
      "speaker": "赵经理",
      "speaker_email": "zhao@clientco.com",
      "原文": "你们做事还是认真的",
      "性质": "正向",
      "source_email_id": "msg-uvw@..."
    }
  ],

  "流失预警信号": [                                    // array<object>
    {
      "信号": "决策者亲自施压",
      "强度": "高",                                    // enum: 高 | 中 | 低
      "时间": "2026-04-22",
      "rule_ref": "R-04",
      "source_email_ids": ["msg-xyz@..."]
    },
    {
      "信号": "PRJ-001 stall 11 天",
      "强度": "中",
      "时间": "2026-05-09",
      "rule_ref": "R-01"
    }
  ],

  "老板视角建议": "本周内安排老板亲自给王总通一次电话——执行层已经救不回来了",

  "_meta": {
    "created_at": "2025-06-01T09:00:00Z",
    "updated_at": "2026-05-09T07:30:12Z",
    "atlas_version": "v0.4",
    "last_andon_alert_at": "2026-05-08T07:30:00Z",
    "last_andon_acknowledged_at": null
  }
}

Customer Health Score (CHS) formula

CHS = 100 × (
    0.4 × project_health
  + 0.3 × normalize(sentiment_trend_30d, [-1,1] → [0,1])
  + 0.2 × email_frequency_normalcy
  + 0.1 × monetary_scale
)

tier:
  CHS >= 80  → 绿(健康)
  60 <= CHS < 80 → 黄(注意)
  CHS < 60   → 红(危急)

Score is clamped to [0, 100] and rounded to nearest integer.

Andon Alert triggers

Fire to state/runs/alerts.json (and email + WeChat if configured) when:

  1. Tier downgrade健康度.档位 drops from 绿→黄 or 黄→红
  2. Strong-negative VoC — new entry in VoC_关键原话_30d with 性质 == "强负向"
  3. Multi-signal churn — ≥ 2 active 流失预警信号 simultaneously

Suppression: same (customer_id, trigger_type) does not re-fire within 24h of last_andon_acknowledged_at.

Cross-customer data isolation

When claw-report-writer renders a customer-specific report:

  • Read ONLY this customer's JSON file
  • Read ONLY projects whose 客户方 matches this customer's id
  • Read ONLY people who appear in this customer's 我方接口人
  • Never include comparison metrics ("compared to other customers")

This isolation is enforced at the file-read layer, not just at template-render time.

Boss override format

OVERRIDE CUST CUST-clientco lifecycle_stage="Active"
OVERRIDE CUST CUST-clientco merge_into="CUST-clientco-group"
OVERRIDE CUST UNCLASSIFIED-newdomain.com promote_as="CUST-newprospect"

Display rules for claw-report-writer

  • Daily Brief: only customers with tier change or new churn signal in last 24h
  • Weekly Rollup: top 5 customers by CHS movement (up or down)
  • Monthly Health Report: one full page per Active or At-Risk customer
  • Andon Alerts: red customers with new strong-negative VoC, real-time

Privacy

  • Right-to-delete: atlas-customer-purge --id CUST-clientco wipes all related project state, removes person↔customer associations, writes tombstone
  • Audit log preserved (anonymized) for compliance