SuperAPI AI Directory

cheat-shoot

General & other

View repository

Updated 10-15 23:42

About this skill

/cheat-shoot — register shooting complete + create video folder + (if script changed) trigger v2 prediction

Advance a video from the "prediction written, not shot" state to the "shot, not published" state. This step:

  1. Create videos/<同 id>/ directory (if not already present)
  2. Ask the user: "Is the script used during actual shooting consistent with scripts/<id>.md ?"
  3. Compute diff — exceeds V2_TRIGGER_THRESHOLD (default 30%) → delegate to /cheat-predict — mode: v2 append to the original prediction file ## 预测 v2 section
  4. Add the video folder to the state.shoots queue, buffer +1

cheat-shoot itselfdoes notwrite prediction content — all prediction persistence logic is in cheat-predict. cheat-shoot is only responsible for detecting script changes + dispatching.

Why a separate skill:

  • The buffer warning system needs to clearly distinguish "shot" vs "published". Videos can be shot in batches (5 in a day), published spread out (1 per day)
  • "Actual shooting script" ≠ "pre-shoot draft" is the norm. This step is the entry point for making the diff explicit, triggering v2 re-judgment, and collecting "user script-change pattern" signals
  • The difference between v2 prediction and v1 prediction is itself evidence of rubric upgrading — e.g., v1 gives ER=4, v2 gives ER=5 (the user's script change increased hook strength), which tells the rubric "this user's ER threshold is inconsistent with my current formula"

Overview

[用户:拍了 scripts/2026-05-04_abc123_停止期待.md]
  ↓
[Phase 0: 解析路径 + 验证 prediction 已存在]
  ↓
[Phase 1: 检查是否已登记(避免重复)]
  ↓
[Phase 2: 建 videos/<id>/ + 询问"实际拍摄稿一致吗?"]
  ↓
[Phase 3: 写 videos/<id>/script.md]
  ↓
[Phase 4: append state.shoots]
  ↓
[Phase 5: 输出 buffer 状态]

Constants

  • REQUIRE_PREDICTION = true — a v1 prediction file must exist before shooting
  • V2_TRIGGER_THRESHOLD = 0.30 — after normalization, char-level diff exceeds 30% → by default recommend v2 re-judgment; below 30%, ask the user whether v2 is still wanted
  • DIFF_METRIC = char_levenshtein_normalized(default)—— via tools/diff_pct.py call: first normalize (remove markdown headers / separators / list markers / decorative punctuation / collapse all whitespace), then compute char-level Levenshtein / max(len_a, len_b). preferred backend rapidfuzz,fallback difflib.SequenceMatcher(stdlib, always available).The old line-level version produced severe false positives in conversational transcription scenarios(draft has long markdown sentences vs whisper transcription's short broken sentences, content almost unchanged but line-level computes ~200% diff) — fixed in PR #14
  • DIFF_METRIC=lines —— legacy fallback: when python3 is completely unavailable or tools/diff_pct.py cannot be found, degrade to diff -u | grep '^[+-]' | wc -l algorithm

Inputs

required source
<scripts-path-or-id> user parameter; if missing, ask
.cheat-state.json state file
scripts/*.md pre-shoot draft
predictions/*.md verify the corresponding prediction exists

Workflow

Phase 0: Parse + validate

  1. Parse the path given by the user — several forms are supported:
    • full path scripts/2026-05-04_abc123_停止期待.md
    • abbreviated 2026-05-04_abc123_停止期待
    • id abbreviation abc123 → glob scripts/*_abc123_*.md find a match
  2. Verify scripts/<id>.md exists: if not → error "cannot find pre-shoot draft"
  3. Verify a corresponding prediction exists predictions/<同名>.md:
    • does not exist → refuse registration, prompt "run /cheat-predict first to write a prediction, otherwise it violates the blind prediction principle — you cannot write the prediction only after shooting, that amounts to writing it after seeing the footage"
    • Exists → Pass

Phase 1: Check for duplicates

Read .cheat-state.json, check whether shoots[] already contains this id:

  • Already exists → Warn "Already registered (X days ago). Do you want to re-register, or publish with /cheat-publish?"
  • Does not exist → Proceed to Phase 2

Phase 2: Create video folder + ask about script consistency

  1. Create directory videos/<id>_<short>/(same naming as scripts/ + predictions/)
  2. Ask the user:
拍 「<title>」 的时候,你实际用的稿子和 scripts/<id>.md 一致吗?

a) 一致——按草稿拍的
b) 改了一些——你能给我看下实际拍摄稿吗?我重新打分一次(v2 预测)
c) 大改了,基本是另一条 → 走 _redo 流程:
   scripts/<id>_redo.md → 重新 cheat-predict → 再 cheat-shoot(原 prediction 留档脱钩)

Phase 3: Write videos//script.md + (b path) trigger v2 prediction

a path (consistent):

  • cp scripts/<id>.md → videos/<id>/script.md
  • script_consistency = consistent
  • Do not re-judge, proceed to Phase 4

b path (changed):

  1. Ask the user for the actual shooting script—pasted text / file path / transcript file

  2. If the user provides it → write to videos/<id>/script.md

  3. If the user did not keep it (improvised) → mark script_lost, write a placeholder file + warn "v2 re-judgment skipped—next time it is recommended to keep a script (even a voice memo transcript)", proceed to Phase 4

  4. If provided: compute diff

    # 解析 cheat-on-content 源码根(cheat-shoot 是 symlink 装的)
    SKILL_REAL="$(readlink -f ~/.claude/skills/cheat-shoot 2>/dev/null || readlink ~/.claude/skills/cheat-shoot 2>/dev/null)"
    if [[ -n "$SKILL_REAL" ]]; then
      REPO_ROOT="$(cd "$SKILL_REAL/../.." && pwd)"
      DIFF_TOOL="$REPO_ROOT/tools/diff_pct.py"
    fi
    
    if [[ -n "${DIFF_TOOL:-}" && -f "$DIFF_TOOL" ]] && command -v python3 >/dev/null 2>&1; then
      # 默认 char-level Levenshtein on normalized text(rapidfuzz preferred, difflib fallback)
      diff_pct=$(python3 "$DIFF_TOOL" "scripts/<id>.md" "videos/<id>/script.md")
    else
      # legacy line-level fallback——只在 python3 或 diff_pct.py 都不可用时用
      added=$(diff -u scripts/<id>.md videos/<id>/script.md | grep -c '^+')
      removed=$(diff -u scripts/<id>.md videos/<id>/script.md | grep -c '^-')
      total_orig=$(wc -l < scripts/<id>.md)
      diff_pct=$(( (added + removed) * 100 / total_orig ))
      echo "⚠️  fallback 到 line-level diff——口语化转录会 inflate diff_pct,可能误触发 v2"
    fi
    

    Why normalize + char-level: line-level diff in creators' real scenarios (the draft is long markdown sentences, the shooting script is short colloquial lines from a whisper transcript) computes ~200% difference but the content is almost unchanged. After normalize, char-level Levenshtein stably reflectscontentdifferences, rather than formatting differences. See tools/diff_pct.py + tools/diff_pct_test.shfor details (3 fixtures all pass on both backends).

  5. Determine v2 trigger:

    • diff_pct >= 30 → by default recommend v2 re-judgment,actively call /cheat-predict — mode: v2 — prediction-file: predictions/<id>.md pass videos/<id>/script.md as input. cheat-predict runs in v2 mode and appends ## 预测 v2
    • diff_pct < 30 → ask the user: "Only N% of the content was changed, do you want to re-judge? Default is no (the v1 prediction is still valid)". If the user says yes → call as above; if the user says no → skip v2, continue to Phase 4
  6. After cheat-predict completes the v2 write to disk, control returns to cheat-shoot to proceed to Phase 4

c path (major change):

  • Do not write videos/<id>/script.md, prompt to follow the _redo flow
  • Exit cheat-shoot (do not proceed to Phase 4)

Phase 4: state update

{
  "shoots": [
    ...,
    {
      "video_folder": "videos/2026-05-04_abc123_停止期待/",
      "prediction_file": "predictions/2026-05-04_abc123_停止期待.md",
      "scripts_path": "scripts/2026-05-04_abc123_停止期待.md",
      "shot_at": "<ISO timestamp>",
      "script_consistency": "consistent" | "modified" | "lost",
      "script_diff_pct": <0-100 int 或 null>,
      "v2_prediction_written": <true/false>,
      "script_hash_at_shoot": "<sha256:12 of videos/<id>/script.md>"
    }
  ]
}

v2_prediction_written: true indicates that the prediction file now has the ## 预测 v2 section; cheat-retro should read v2 to compute deviation;false indicates to continue using v1.

Phase 5: Output buffer status

Immediately after reading state, compute buffer + color (per cadence-protocol.md 's derivation rules):

✅ 已登记拍摄:videos/2026-05-04_abc123_停止期待/
   预测文件:predictions/2026-05-04_abc123_停止期待.md

📦 当前 buffer:3 篇(🟢 绿色,正常)
   按你的 cadence(隔日更)= 6 天 buffer,节奏稳定。

下一步:拍其他候选 / 等下个发布日 / 不动

If the buffer color changed (e.g., from green to blue) → highlight reminder:

📦 当前 buffer:6 篇(🔵 蓝色,**积压**)
⚠️  建议暂停拍摄,全力发布存货 + 复盘。
   按你的 cadence(日更)= 6 天预备,已超过健康上限。

Key Rules

  1. Do not write prediction—shooting ≠ publishing. The prediction is locked at /cheat-predict, shooting is just an event
  2. Do not touch video folder contents—neither script.md nor draft-v0.md is changed
  3. There must be a prediction first—otherwise it violates blind prediction (looking at the footage after shooting and then writing a prediction = data leakage into judgment)
  4. Compute buffer in real time—recompute immediately after each shoot / publish; state.shoots is the ground truth
  5. Batch supported: the user can say "shot X / shot Y / shot Z" three times in a row in one day and register them consecutively

Refusals

  • "Shot X, but I never ran cheat-predict" → Reject. The v1 predictionmust be written before shooting——Writing a prediction after shooting will be influenced by the footage and lead to after-the-fact edits. Please run /cheat-predict to write v1 first, then come back to /cheat-shoot. (Re-judging as v2 is a separate matter—only allowed if v1 already exists + the draft is revised after shooting)
  • "I don't have a video folder, I shoot directly" → ask the user → help them create a video folder + remind them to follow the full process next time; when registering, mark ad_hoc: true
  • "I revised the draft but just overwrite v1, don't keep a v2 section" → refuse. v1 is the archive, v2 is the current judgment—append, don't overwrite. Keeping both sections together is key evidence for rubric learning

Integration

  • Upstream:/cheat-predict finish writing prediction → user shoots → /cheat-shoot register
  • Downstream:/cheat-publish when publishing, remove the corresponding item from state.shoots
  • /cheat-status the dashboard's buffer number comes directly from state.shoots.length
  • /cheat-recommend adjust the recommendation strategy based on the buffer color
  • The SessionStart hook looks at the buffer color to decide the first line of the report

state.shoots data structure

{
  "shoots": [
    {
      "video_folder": "videos/2026-05-04_abc123_停止期待/",
      "prediction_file": "predictions/2026-05-04_abc123_停止期待.md",
      "shot_at": "2026-05-04T18:30:00+08:00",
      "ad_hoc": false  // true if user shot without going through full flow
    }
  ]
}

In ascending order by shot_at —the earliest shot comes first./cheat-status Show a days-since-shoot warning for the earliest item (to avoid having a video that was shot 30 days ago and still not published).