Automates live ballet class timetable, booking, attendance, and membership queries through SSH CLI commands to the MaxNow server. Use when the owner asks for ballet schedules, bookings, or class availability.
Recursos
1Instal·la
npx skillscat add v-ioi-v/maxnow/maxnow-ballet-live Instal·la des del registre de SkillsCat.
Automates live ballet class timetable, booking, attendance, and membership queries through SSH CLI commands to the MaxNow server. Use when the owner asks for ballet schedules, bookings, or class availability.
MaxNow Ballet Live
Always query Wenda live through the MaxNow server. Never read dash/data/ballet.json, ballet.js, browser storage, private ledgers, snapshots, or prior chat results as the answer or as a booking input.
Workflow
- Resolve relative dates in
Asia/Shanghaiand convert them to ISO dates. - Select the smallest live scope that answers the question:
timetable: classes and live availability for one date or a date range.bookings: current booked and waitlisted classes, positions, and cancellation deadlines.attendance: live attendance records; pass a date range when the request supplies one.membership: course-card validity and remaining classes.
- From outside the server, run:
ssh -o BatchMode=yes -o ConnectTimeout=10 ubuntu@43.160.240.244 \
"cd /var/www/maxnow-dashboard && scripts/run_ballet_live_query.sh <scope> [--from-date YYYY-MM-DD] [--through-date YYYY-MM-DD]"When already running on the MaxNow server, omit SSH and run the command after changing to /var/www/maxnow-dashboard.
Examples:
scripts/run_ballet_live_query.sh timetable --from-date 2026-07-28 --through-date 2026-08-03
scripts/run_ballet_live_query.sh bookings
scripts/run_ballet_live_query.sh attendance --from-date 2026-07-01 --through-date 2026-07-31
scripts/run_ballet_live_query.sh membership- Require a successful JSON response with all of:
"source":"wenda-live""status":"success""live":true- a current
fetchedAt
- Answer from
dataand state the live query time. If the command fails, report the safe error and say no live data was returned. Do not fall back to cached data. - For
attendanceonly, the shared normalization rule returns李俊when Wenda leaves the teacher field empty, except that the owner-confirmed 2026-08-07 19:45–21:15 ballet L1 record returns张瀚泽. Do not apply defaults or history corrections to timetable, booking, or waitlist records.
Booking Workflow
Only book when the owner explicitly asks to book one or more exact classes. An exact class requires date, start time, end time, course name, teacher, and venue. Do not infer a different class when any field does not match.
- Build this JSON on stdin:
{
"courses": [
{
"date": "2026-07-30",
"startTime": "20:15",
"endTime": "21:15",
"courseName": "肌肉素质",
"teacher": "戴俊瑶",
"venue": "小教室"
}
],
"confirm": false
}- Run a live preflight through the repository runner:
scripts/run_ballet_booking.sh dry-runThe preflight may use Wenda's fixed read-only POST checks for eligible cards and booking rules. It must never call do_addbook. Require live=true and mutationAttempts=0; target records must be ready, already_booked, or activation_required. The last status means activation is planned but has not occurred; other preflight failures must not be bypassed.
- If the owner has explicitly requested those exact classes in the current request, change only
confirmtotrueand run:
scripts/run_ballet_booking.sh executeThe runner performs a unified live preflight, then books courses sequentially. Before each mutation it rechecks availability, eligible card, and booking rules. It sends at most one do_addbook request per course, immediately verifies the result from live bookings, returns one result per course, and stops after an ambiguous or authentication failure. Never retry an ambiguous mutation.
For multiple exact classes without an owner-specified order, sort them by the permanent weekday priority 周六 > 周日 > 周五 > 其他日期, then keep the original order within the same weekday.
- Report only the safe per-course result. A course is booked only when its result is
status=bookedand live verification returnsbookingStatus=booked. Card choice follows the owner-approved expiry order throughballet_card_policy.py: earliest expiry first, then later expiries; a definite card/rules rejection advances before booking submission. When no active applicable card works, execution may activate the applicable unactivated card with the fewest remaining classes. Dry-run reportsactivation_requiredwith zero mutations; it may proceed to execute only for owner-confirmed exact targets under this already-approved activation policy. Never bypass anactivation_unknownresult or delete the private journal to retry.
Sunday Automatic Booking
The enabled production fast path runs entirely on the MaxNow server. It arms at Sunday 14:19:35 Beijing time, warms the live session, waits until 14:20:00, and submits configured targets sequentially. It does not invoke Codex, this Skill, or SSH on the timing-critical path.
After every production fast-path execution reaches either a successful or failed terminal state, systemd immediately starts the existing GET-only rolling ballet sync so the MaxNow panel reflects the latest booking and waitlist state. This post-run refresh is outside the mutation-critical path and does not change the fast-path result.
After release, the fast path reads Monday through Saturday timetable pages and dynamically discovers every matching occurrence. Each discovered occurrence is an independent failure domain. Match exactly one live course by date, exact discovered course name, course type/level, start/end time, and selected venue. Teacher is display-only and must not affect matching or the occurrence idempotency key, so a substitute teacher does not block a configured rule. Transient pre-mutation failures and an explicit NOTOPEN response may be retried three times with short bounded backoff. A course-level failure or ambiguous mutation must not block later targets. Never retry an ambiguous mutation because Wenda may already have accepted it; include it in the final unified live-bookings verification instead. Stop later targets only for a global safety failure such as expired authentication, invalid configuration, or a changed page/endpoint contract.
For these configured recurring targets only, allowWaitlist=true authorizes the same exact-course fast path to join the waitlist when live availability is queue_available. If availability is available, book normally. If it is already booked or waitlist, do not submit again. Final verification must preserve Wenda's actual bookingStatus (booked or waitlist) and a safe positive waitlistPosition when present. This authorization does not extend to conversational bookings or any unconfigured class.
Current recurring rules are:
- Monday through Friday: every standard ballet L1 occurrence starting at or after 18:40, any teacher.
- Monday through Friday: every standard ballet L1.5 occurrence starting at or after 18:40, any teacher.
- Monday through Friday: only a course whose normalized name is exactly
软开or软开课and starts at or after 18:40, any teacher. - Saturday, only classes ending strictly before 18:00: the same standard ballet L1, standard ballet L1.5, and exact-name
软开/软开课rules. - Sunday courses are excluded.
软开专项,软开专项【前后腿】,软开-胯, and any other merely soft-open-classified near match are excluded. - For the same occurrence, prefer
大教室; use小教室only when the large-room tier has no match. The selected tier must contain exactly one course.
For the Sunday fast path, process dates in the order Tuesday, Saturday, Friday, Monday, Wednesday, Thursday; within each day process L1, L1.5, then exact-name soft-open. Weekday selection prefers Li Jun (blank teacher treated as Li Jun); Saturday has no teacher tier. Teacher is excluded from the occurrence idempotency key. Timetable GETs may use at most three workers; one background card/rules worker plus the serial submission stage keep preflight concurrency at most two. Preflight expires after fifteen seconds, and the selected card rules are always rechecked immediately before submission. Actual booking or waitlist mutations must remain strictly serial. Activation may run only at that serial stage, at most one card per execution, with an independent live-card verification and a persistent private attempted/verified journal. Any unknown activation is a global stop across later courses and survives process restart. Final booking-detail verification may use at most three read-only workers.
To query the automation plan and safe result ledger, run:
ssh -o BatchMode=yes -o ConnectTimeout=10 ubuntu@43.160.240.244 \
"cd /var/www/maxnow-dashboard && scripts/run_ballet_booking_fast.sh status"The automation status ledger is allowed only for plan, last/next run, configured targets, and aggregate result questions. It is not a source for course availability. For any timetable or availability question, use the live query workflow above.
Do not manually start the production service or run book_ballet_fast.py execute from a conversation. Changes to automatic targets require a reviewed configuration change, tests, deployment, and a refreshed safe status snapshot.
Timetable Answer Contract
- Treat generic questions such as “有什么课程” or “有什么可以约的课” as requests for every returned course type. Do not filter
courseTypeby default; include ballet, conditioning, soft-open, technique, and any future types returned by the live source. - Apply a course-type filter only when the owner explicitly says “只看”, “仅看”, “只想看”, or otherwise clearly limits the answer to named course types. Do not interpret the umbrella phrase “芭蕾课程” by itself as
courseType=ballet. - For availability questions, list future records with
availability=availableas the primary result. State the number ofqueue_availablerecords separately, but do not mix waitlist-only rows into the directly bookable list unless the owner asks to see them. - Group rows by date using
**周X M/D**. Format every directly bookable row as- HH:MM–HH:MM 课程名|老师|教室|余N, where余Niscapacity - bookedCount. - Include both start and end time on every course row. End with the live query time and state that no cache was used.
Safety Boundary
- Use only the repository runners. They create hardened transient systemd units, decrypt the host-bound credential into the unit credential directory, and remove that runtime directory when done.
- Allow only the four scopes and ISO date arguments. A timetable request may span at most 14 days.
- Never print, copy, inspect, hash, summarize, or ask the owner for PHPSESSID. Never read
/etc/credstore.encrypteddirectly. - For ordinary queries, never use POST. For an explicitly confirmed booking, allow fixed card-eligibility and booking-rules checks, one
do_addbookrequest per exact course, and the owner-approved single-card activation protocol throughrun_ballet_booking.sh. Activation is checked through the official card-detail button andgetopencardinfo, submitted once throughopencard, and independently verified. No buying, paying, renewing, or activating from queries / preview / dry-run is permitted. - Never use cancellation, transfer, payment, login, or arbitrary POST endpoints. Waitlist mutation is forbidden for ordinary queries and conversational booking; it is allowed only inside the enabled Sunday fast path for an exact configured target with
allowWaitlist=true. - Never expose source record IDs, member identifiers, raw HTML, response bodies, Cookie headers, credential paths, unit names, or internal logs.
- Treat
auth_required,source_changed,parse_error,unknown_result, and ambiguous responses as fail-closed. If any mutation was attempted and the result is ambiguous, report that verification is required; never claim failure or retry. - For the Sunday automatic fast path only, fail-closed is scoped per course: an ambiguous mutation is never retried, but later configured courses still proceed and all ambiguous/successful submissions are verified together. Authentication, configuration, and source-contract failures remain global stops.