OUTPUT #738 | 14885 karakter | 341 satır
========== YENİ KOMUT | 17.09.2026 20:06:12 ==========
========== YENİ KOMUT | 17.09.2026 20:06:12 ==========
/home/hermes/.hermes/skills/media/shorts-core/SKILL.md
187-### ASSET-001 — Pre-casting visual inspection diagnostic
188-
189-Bu tanı koşusunda asset/casting kararını yalnız metadata, dosya adı veya arama açıklamasından verme.
190:Gerekli olduğunda aday gerçek footage/source/range/assetleri `vision_analyze` ile gerçekten gör.
191-
192-Değerlendir:
193-- gerçek hareket ve görüntü kalitesi;
--
231-
232-### Faz 3 — Tek görsel QA geçidi
233-
234:Deterministic pipeline PASS verdikten sonra yalnız final contact sheet'i `vision_analyze` ile değerlendir.
235-
236-Kontrol et:
237-
/home/hermes/.hermes/plugins/shorts-production-guard/__init__.py
226- return target
227- if tool_name == "terminal":
228- low = str(args.get("command") or "").lower()
229: # Normal preflight/proof-check/segment-build/pipeline runs are the public
230- # interface and remain available. Introspection is rediscovery.
231- if any(marker in low for marker in ("--help", "grep ", "rg ", "cat ", "sed ", "python -c")):
232- return target
--
246- return _block(
247- "Shorts production guard: normal production must use the documented interface "
248- f"instead of re-reading {target} to rediscover schema. Run the canonical "
249: "preflight/proof-check/pipeline command. Source and tests remain readable in an "
250- "explicit engineering/system-change task."
251- )
252- _CANONICAL_READS.add(key)
--
256- return {"action": "block", "message": message}
257-
258-
259:def _runtime_proof_fingerprint(data: dict) -> str:
260: """Mirror the canonical proof fingerprint so accepted proof can be frozen at runtime."""
261- creative = data.get("creative_intent") or {}
262: gate = data.get("proof_gate") or {}
263- candidates = gate.get("candidates") or []
264-
265- normalized = []
--
327- payload = {
328- "creative_intent": {
329- "promise": creative.get("promise"),
330: "primary_visual_proof": creative.get("primary_visual_proof"),
331- "hook_visual_goal": creative.get("hook_visual_goal"),
332- "payoff": creative.get("payoff"),
333- },
334: "proof_gate": {
335- "mode": gate.get("mode"),
336- "candidates": normalized,
337- },
--
342- ).hexdigest()
343-
344-
345:def _proof_freeze_block(tool_name: str, args: dict) -> Optional[dict]:
346: """After a valid proof PASS, prevent edits that invalidate the accepted proof."""
347- if tool_name not in {"patch", "write_file", "execute_code"}:
348- return None
349-
--
355- for marker in ("write_file(", "write_text(", ".write(", "json.dump(", "open(")
356- ):
357- return _block(
358: "Shorts production guard: PROOF_FREEZE — do not mutate manifest.json through "
359: "execute_code after an accepted proof. Use patch/write_file instead so the runtime "
360: "can compare the prospective proof fingerprint and allow proof-irrelevant edits "
361: "while blocking changes to accepted creative proof/casting."
362- )
363- return None
364-
--
375- try:
376- current_text = path.read_text(encoding="utf-8")
377- current = json.loads(current_text)
378: gate = current.get("proof_gate") or {}
379- receipt_value = gate.get("receipt")
380- receipt = (
381- Path(str(receipt_value)).expanduser().resolve()
382- if receipt_value
383: else (path.parent / "proof_gate" / "proof_receipt.json").resolve()
384- )
385- if not receipt.exists():
386- return None
--
388- if accepted.get("pass") is not True:
389- return None
390-
391: current_fp = _runtime_proof_fingerprint(current)
392- if accepted.get("fingerprint") != current_fp:
393- # Already stale: do not create a new policy trap here.
394- return None
--
412- )
413-
414- prospective = json.loads(prospective_text)
415: if _runtime_proof_fingerprint(prospective) != current_fp:
416- return _block(
417: "Shorts production guard: PROOF_FREEZE — accepted proof is locked. "
418: "Do not change creative_intent, proof candidates, or selected footage/casting "
419- "after Vision PASS. Continue with TTS/render/final QA using the accepted plan. "
420: "A genuine proof failure must be handled before acceptance, not by reopening "
421: "the proof loop after PASS."
422- )
423- except Exception:
424- return None
425- return None
426-
427-
428:def _proof_attempt_state_path(image_path: Path, pending: Optional[dict] = None) -> Path:
429: """Use one attempt ledger per canonical proof receipt, not per proofN workdir."""
430- if isinstance(pending, dict):
431- receipt = pending.get("receipt")
432- if isinstance(receipt, str) and receipt.strip():
433- try:
434: return Path(receipt).expanduser().resolve().parent / "proof_attempt_state.json"
435- except Exception:
436- pass
437: return image_path.parent / "proof_attempt_state.json"
438-
439-
440:def _read_proof_attempt_state(image_path: Path, pending: Optional[dict] = None) -> dict:
441: path = _proof_attempt_state_path(image_path, pending)
442- try:
443- if path.exists():
444- value = json.loads(path.read_text(encoding="utf-8"))
--
448- return {}
449-
450-
451:def _write_proof_attempt_state(
452- image_path: Path, state: dict, pending: Optional[dict] = None
453-) -> None:
454- try:
455: path = _proof_attempt_state_path(image_path, pending)
456- path.parent.mkdir(parents=True, exist_ok=True)
457- tmp = path.with_suffix(path.suffix + ".tmp")
458- tmp.write_text(json.dumps(state, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
--
464-def _direct_render_bypass(tool_name: str, args: dict) -> bool:
465- """Block manual TTS/final assembly during normal Shorts production.
466-
467: Asset inspection, proof generation and deterministic QA remain available.
468- Final production must go through the canonical shorts_fast_pipeline.
469- """
470- if tool_name == "terminal":
--
535- return None
536-
537-
538:def _normalized_proof_token(value: Any) -> str:
539- """Accept the harmless exact-prefix variation repeatedly emitted by Vision."""
540- token = str(value or "").strip()
541- prefix = "HERMES_PROOF_GATE::"
542- return token[len(prefix):] if token.startswith(prefix) else token
543-
544-
545:def _proof_verdict_accepted(verdict: Any, token: str) -> bool:
546: """Accept proof only when every selected footage role is unambiguous."""
547- return bool(
548- isinstance(verdict, dict)
549- and verdict.get("verdict") == "PASS"
550: and verdict.get("verifier") == "vision_analyze"
551: and verdict.get("primary_visual_proof") is True
552- and verdict.get("hook_visual_goal") is True
553: and verdict.get("proof_visible_and_unmistakable") is True
554- and verdict.get("casting_subjects_clear") is True
555: and _normalized_proof_token(verdict.get("proof_token")) == token
556- )
557-
558-
--
602- if rediscovery_block:
603- return rediscovery_block
604-
605: freeze_block = _proof_freeze_block(tool_name, args)
606- if freeze_block:
607- return freeze_block
608-
609- if not alternate_method and not explicit_system_change and _direct_render_bypass(tool_name, args):
610- return _block(
611- "Shorts production guard: direct TTS/final assembly outside the canonical pipeline "
612: "is blocked during normal production. Use shorts_fast_pipeline.py. If proof Vision "
613: "cannot issue a valid receipt, stop with QA_UNAVAILABLE; do not build a fallback final."
614- )
615-
616- # Explicitly requested alternate/code-driven workflows remain available.
--
629- if tool_name in {"browser_vision", "computer_use"} and not alternate_method:
630- return _block(
631- "Shorts production guard: this QA fallback is disabled during normal production. "
632: "Use vision_analyze as the primary visual QA path; if Vision is unavailable after "
633: "the permitted retry, continue with controlled QA_UNAVAILABLE rather than inventing a fallback."
634- )
635-
636: if tool_name == "vision_analyze":
637- image_url = str(args.get("image_url") or "")
638- question = str(args.get("question") or "").strip()
639- raw = image_url[7:] if image_url.startswith("file://") else image_url
--
645- # Use visual inspection only when it helps choose footage that actually fulfills
646- # the creative contract. Existing duplicate/no-progress and other guards remain active.
647-
648: if image_path.name == "proof_contact_sheet.jpg":
649: pending_path = image_path.parent / "proof_pending.json"
650- current_fingerprint = None
651- pending = {}
652- try:
--
655- current_fingerprint = pending.get("fingerprint")
656- except Exception:
657- pending = {}
658: proof_state = _read_proof_attempt_state(image_path, pending)
659-
660- if (
661: int(proof_state.get("failed_attempts") or 0) >= 2
662- and current_fingerprint
663: and proof_state.get("last_fingerprint") == current_fingerprint
664- ):
665- return _block(
666: "Shorts production guard: PROOF_STRATEGY_EXHAUSTED — this proof strategy "
667- "already failed initial review plus one repair. Do not retry Vision on the "
668: "same accepted candidates/casting. Materially change the proof footage or "
669: "casting, rerun proof-check, and continue the production autonomously."
670- )
671-
672- # Content identity matters more than filename: a repaired final_contact_sheet
--
712- or args.get("file_path")
713- or ""
714- )
715: if path.endswith("proof_receipt.json") or path.endswith("proof_pending.json"):
716- return _block(
717: "Shorts production guard: proof state is runtime-owned. "
718: "Do not write or patch proof receipts/pending attestations manually; "
719: "only a real vision_analyze PASS may issue the receipt."
720- )
721- if any(path.startswith(prefix) for prefix in _PROTECTED_PREFIXES):
722- return _block(
--
727- if tool_name == "terminal":
728- cmd = str(args.get("command") or "")
729- low = cmd.lower()
730: if "proof_receipt.json" in low or "proof_pending.json" in low:
731- return _block(
732: "Shorts production guard: proof state is runtime-owned. "
733: "Do not create, edit, copy, delete, or inspect proof receipt/pending files "
734- "through terminal commands during production."
735- )
736- if (
--
814- else:
815- accepted = (
816- verdict.get("verdict") == "PASS"
817: and verdict.get("verifier") == "vision_analyze"
818: and verdict.get("post_repair_semantic_verified") is True
819: and _normalized_proof_token(verdict.get("repair_token")) == token
820- )
821- failed = verdict.get("verdict") == "FAIL"
822- state["state"] = "verified" if accepted else ("failed" if failed else "unverified")
823- state["verification_pending"] = False
824- state["claim_fixed_allowed"] = accepted
825- state["verification"] = {
826: "verifier": "vision_analyze",
827- "verdict": verdict.get("verdict"),
828- "artifact_sha256": state.get("artifact_sha256"),
829- "contact_sheet_sha256": state.get("contact_sheet_sha256"),
--
852- status: str = "",
853- **_: Any,
854-) -> None:
855: if tool_name != "vision_analyze":
856- return
857-
858- active, _, _ = _production_context(session_id)
--
896- image_path, contract_question, result, session_id, turn_id, tool_call_id
897- )
898-
899: if image_path.name != "proof_contact_sheet.jpg":
900- return
901-
902: pending_path = image_path.parent / "proof_pending.json"
903- if not pending_path.exists():
904- return
905-
--
908- except Exception:
909- return
910-
911: token = str(pending.get("proof_token") or "")
912- if not token or f"HERMES_PROOF_GATE::{token}" not in contract_question:
913- return
914-
--
929- if not verdict:
930- return
931-
932: accepted = _proof_verdict_accepted(verdict, token)
933- if not accepted:
934- if verdict.get("verdict") == "FAIL":
935: state = _read_proof_attempt_state(image_path, pending)
936- fingerprint = pending.get("fingerprint")
937- if state.get("last_fingerprint") != fingerprint:
938- state["failed_attempts"] = 0
--
940- state["last_verdict"] = "FAIL"
941- state["last_fingerprint"] = fingerprint
942- state["updated_at"] = time.time()
943: _write_proof_attempt_state(image_path, state, pending)
944- return
945-
946: state = _read_proof_attempt_state(image_path, pending)
947- state["accepted"] = True
948- state["last_verdict"] = "PASS"
949- state["last_fingerprint"] = pending.get("fingerprint")
950- state["updated_at"] = time.time()
951: _write_proof_attempt_state(image_path, state, pending)
952-
953- try:
954- receipt = Path(str(pending["receipt"])).expanduser().resolve()
--
956- obj = {
957- "pass": True,
958- "receipt_source": "shorts-production-guard/post_tool_call",
959: "verifier": "vision_analyze",
960- "fingerprint": pending["fingerprint"],
961- "contact_sheet": str(image_path),
962- "contact_sheet_sha256": pending["contact_sheet_sha256"],
root@213-238-170-219:~#