403Webshell
Server IP : 3.147.158.171  /  Your IP : 216.73.216.88
Web Server : Apache/2.4.67 (Amazon Linux) OpenSSL/3.5.5
System : Linux ip-172-31-2-178.us-east-2.compute.internal 6.1.172-216.329.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Wed May 20 06:31:34 UTC 2026 x86_64
User : ec2-user ( 1000)
PHP Version : 8.4.21
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /tsai/repo/.claude/skills/schedule-characters/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /tsai/repo/.claude/skills/schedule-characters/SKILL.md
---
name: schedule-characters
description: Set calendar-based article posting schedules for characters on a site
argument-hint: <env> <site_slug> "<description>"
---

# Schedule Characters

Configure calendar-based `articleSchedule` values for characters on a production site, based on a loose natural-language description of when they should post.

**Arguments:** $ARGUMENTS

Parse as:
- `env` — first token: `tsai` or `scike`
- `site_slug` — second token (e.g. `jpt`, `guitar`, `news`)
- `description` — remaining text (may be quoted), describing the desired posting cadence

If any of these are missing, ask the user before proceeding.

**Scope:** this command sets a character's calendar `articleSchedule` (days/hours). Calendar schedules are the only posting mechanism — a character posts only when it has a schedule whose day constraints match.

---

## Environment constants

| env | SSH host | Repo path | TSAI_ENV |
|-----|----------|-----------|----------|
| `tsai` | `ssh -i ~/.ssh/tsai.pem ec2-user@3.147.158.171` | `/tsai/repo` | `production` |
| `scike` | `ssh -i ~/.ssh/tsai.pem ec2-user@scike.ai` | `/data/tsai` | `scike_ai` |

---

## Step 1 — Get cb_host and list characters with current article schedules

Get the `cb_host` for the site:

```bash
ssh -i ~/.ssh/tsai.pem ec2-user@{host} \
  "cd {repo}/api && source venv/bin/activate && \
   TSAI_ENV={tsai_env} python3 -c \"
from app.services.site_config_service import SiteConfigService
svc = SiteConfigService()
site = svc.get_site_by_slug('{site_slug}')
if not site:
    slugs = sorted(s.slug for s in svc.get_all_sites())
    print('NOT_FOUND: ' + ', '.join(slugs))
else:
    print('CB_HOST:' + site.cb_host)
\""
```

If the output starts with `NOT_FOUND`, stop and tell the user which slugs are available.

Then list characters using the `cb_host` as the Origin header:

```bash
ssh -i ~/.ssh/tsai.pem ec2-user@{host} \
  "curl -s -H 'Origin: https://{cb_host}' \
    'http://localhost:8000/api/v1/cms/characters/' | \
    python3 -c \"
import sys, json
data = json.load(sys.stdin)['data']
for c in data:
    print(json.dumps({
      'name': c['name'],
      'slug': c['slug'],
      'enabled': c.get('enabled'),
      'systemWide': c.get('systemWide'),
      'articleSchedule': c.get('articleSchedule'),
    }))
\""
```

Present a compact table of name, slug, enabled, systemWide, and current `articleSchedule` (daysOfWeek / daysOfMonth / preferredHours).

Only characters that are `enabled` and not `systemWide` are candidates for scheduling unless the user explicitly names a systemWide character.

---

## Step 2 — Propose a concrete plan

Translate the description into per-character calendar schedules using these rules:

- **Named characters take precedence.** If the description names specific characters (e.g. "schedule Suzie for Tuesday mornings"), schedule only those and leave others untouched.
- **Distribute for coverage.** If the description asks for aggregate coverage ("at least one character posts each day"), assign `daysOfWeek` across enabled, non-system-wide characters so the union covers 0–6 with no required duplicates.
- **Time-of-day mapping** for `preferredHours`:
  - morning → `8,9,10`
  - midday/noon → `11,12`
  - afternoon → `13,14,15`
  - evening → `18,19,20`
  - leave empty if unspecified
- **Cadence mapping:**
  - weekly / "once a week" / day-named phrases → `daysOfWeek`
  - monthly / "on the Nth" → `daysOfMonth`
  - do not set both unless the user explicitly asked for both
- **Day numbering:** 0=Sun, 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat.

Output one line per affected character:

```
<name> (<slug>) — daysOfWeek=[…]  daysOfMonth=[…]  preferredHours=[…]
```

Also list any characters whose current `articleSchedule` should be cleared (only if the description implies it).

---

## Step 3 — Confirm

Ask the user to approve the plan or suggest edits. **Do not proceed to Step 4 until the user confirms.**

---

## Step 4 — Apply

For each affected character, SSH to the server and run `schedule_character.py`. Use `--clear` for removals; otherwise pass the relevant day/hour CSV flags.

**Always invoke with `python3 -u`** (unbuffered stdout). Each invocation reloads site configs from Drupal and is slow, so a multi-character batch takes a while; without `-u`, Python withholds stdout when it isn't a terminal and progress appears frozen even though the remote work is proceeding.

```bash
ssh -i ~/.ssh/tsai.pem ec2-user@{host} \
  "cd {repo}/api && source venv/bin/activate && \
   python3 -u schedule_character.py '{slug}' '{site_slug}' \
     --env {tsai_env} \
     --days-of-week '{dow_csv}' \
     [--days-of-month '{dom_csv}'] \
     [--preferred-hours '{hours_csv}']"
```

Clear variant:

```bash
ssh -i ~/.ssh/tsai.pem ec2-user@{host} \
  "cd {repo}/api && source venv/bin/activate && \
   python3 -u schedule_character.py '{slug}' '{site_slug}' \
     --env {tsai_env} --clear"
```

Omit empty flags entirely rather than passing empty strings. If any call errors, report it and stop before running the rest.

For a multi-character batch, loop in a single SSH session. Even with `-u`, treat the streamed stdout as progress only — do **not** judge completion from it. Confirm the result with the Step 5 re-query, which reads the live state directly.

---

## Step 5 — Report result

Re-query the characters list (the same call as Step 1) and use it as the authoritative "after" state. This is the source of truth — the per-call stdout from Step 4 can lag behind the actual server state due to output buffering, so never report completion from stdout alone.

For each updated character, show:

- **Name / slug**
- **Before:** old schedule (from Step 1)
- **After:** new schedule (from the Step 5 re-query)

Remind the user:

- A character posts only when it has a calendar schedule whose day constraints match; characters with no schedule never post.
- Changes are picked up on the next run of the systemd article timer on the server.

Youez - 2016 - github.com/yon3zu
LinuXploit