| name | monitoring-weekly |
| description | Use when: kullanıcı "weekly check", "haftalık monitoring", "drift check
+ GSC anomaly + budget burn", "weekly health report", "haftalık sağlık
raporu", "haftalık monitoring özeti" der ya da /pseo-monitoring-weekly
çağırır; week range filter events.jsonl + drift-check output reuse +
GSC week-over-week delta + budget burn rate aggregation →
outputs/reports/{date}-monitoring-weekly.md.
Wave-1a scope (truth-in-advertising): drift + portfolio health
snapshot ACTIVE; GSC weekly anomaly ACTIVE (median+MAD modified-z,
R-141, sourced from _state/metrics/gsc-weekly.jsonl — NOT master.xlsx);
ONLY budget-burn (cost.credits) aggregation remains a PLACEHOLDER
deferred to Phase 14+.
Also use when: cron scheduled weekly run her Pazartesi 09:00 UTC
report-only mode; reporting suite extension Phase 9 8 reporting skill
no-write paterni reuse; Foundational Principle 1 truth-verifiable
enforcement audit-only (Wave-1a inline: consistency-report.json +
portfolio.json + _state/metrics/gsc-weekly.jsonl kaynaklı; master.xlsx
read YOK, sadece budget-burn Phase 14+ scope;
fabrikasyon yok); manager portfolio-overview öncesi tek-proje haftalık
sağlık özeti istediğinde.
Do not use when: ad-hoc daily check (out of scope, daily skill ayrı —
bu skill rolling 7-day window aggregator); events.jsonl empty week
range (DURUR #1 SKIP, no report write); GSC api auth fail (out of
scope, gsc-bootstrap skill önce çalışmalı); template path missing →
inline fallback (DURUR #4 AMBER, manuel inceleme); MAD anomali
severity=RED ise CRITICAL escalation (DURUR #5 — ikinci audit satırı,
median+MAD modified-z R-141; ≥6 tam ISO hafta yoksa insufficient_history
dürüst render, alarm değil); master.xlsx WRITE talep edilirse
YASAK (Phase 9 reporting paterni: 8 skill no-write invariant).
|
| version | 1.0 |
| status | wip |
| category | reporting |
| inputs | {"week_start":{"type":"string","required":true,"description":"YYYY-MM-DD format week start date (inclusive). Window kapsamı: week_start..week_end. Geçersiz format → DURUR validation hata."},"week_end":{"type":"string","required":false,"default":"today","description":"YYYY-MM-DD format week end (inclusive). Default 'today' (run-time date.today() ile çözülür). week_start sonrası olmalı."}} |
| outputs | ["_state/events.jsonl","outputs/reports/{date}-monitoring-weekly.md"] |
| consumes | ["drift-check:_state/cache/consistency-report.json","init-project:shared/portfolio.json","templates/reports/monitoring-weekly.template.md","gsc-pull:_state/metrics/gsc-weekly.jsonl"] |
| produces | [] |
| triggers | {"manual":["/pseo-monitoring-weekly"],"natural_language":"\"weekly check\", \"haftalık monitoring\", \"drift check + GSC anomaly +\nbudget burn\", \"weekly health report\", \"haftalık sağlık raporu\",\n\"monitoring weekly\", \"haftalık health check\"\n","hooks":[],"scheduled":[{"cron":"0 9 * * 1","mode":"report-only"}]} |
| mcp_tools | {"required":[],"optional":[]} |
| budget | {"uses_paid_mcp":false,"estimated_credits":0} |
| autonomy | {"confidence":"HIGH","requires_approval":false,"safe_auto_execute":true} |
monitoring-weekly — reporting skill (Phase 12 Wave 2, W-G6)
Weekly health check aggregator. Wave-1a inline scope (what the
runtime actually reads): drift-check output
(_state/cache/consistency-report.json) + project health
(shared/portfolio.json) + the GSC weekly anomaly ledger
(_state/metrics/gsc-weekly.jsonl, written by gsc-pull Step 7b), then
renders outputs/reports/{date}-monitoring-weekly.md. No MCP, no
DFS, no master.xlsx WRITE — strict read-only.
GSC anomaly is ACTIVE (GAP-M4 / R-141). It uses the robust
median + MAD modified z-score (NIST/Iglewicz–Hoaglin, |M| ≥ 3.5) with
percent + absolute floors over ≥6 complete ISO weeks, replacing the old
5-standard-deviation / trailing-8-week-mean placeholder (which was both
statistically meaningless at n≈8 and unimplementable — the
master.xlsx[gsc_performance] sheet is a recent-vs-previous SNAPSHOT
with no date column, so it never held a weekly series; the
_state/metrics/gsc-weekly.jsonl ledger does). An anomaly whose week
overlaps a Google Ranking-update window (google-update-calendar.json,
R-137) is capped at AMBER with an attribution caution. Detection is
imported from scripts.reporting.weekly_anomaly + scripts.reporting.update_calendar.
Still deferred to Phase 14+ (PLACEHOLDER string, NOT an active read):
budget burn rate (events.jsonl cost.credits aggregation per day vs
project-config.budget_credits_per_day baseline). The inline runtime
does not open master.xlsx or project-config — it reads the
consistency-report + portfolio + weekly-ledger snapshots above.
This skill follows the Phase 9 reporting convention authority
established by skills/reporting/weekly-summary/SKILL.md (W-E2 — local
aggregation, READ-ONLY contract on master.xlsx) and
skills/reporting/portfolio-overview/SKILL.md (W-E5 — multi-project
no-write aggregator). The 8 Phase 9 reporting skills share the
no-write invariant — transaction.append, transaction.update,
transaction.delete and wb.save MUST NOT appear anywhere in
production paths. The test suite enforces this with a grep sentinel
(the call-site syntax with the trailing ( paren is the actual
forbidden token; prose mentions without parens are allowed).
Schema-First Override (Lesson 7+23+31, W-G1+W-G2+W-G3+W-G4 paterni)
The brief sketched event_kind=audit + event_type=monitoring_completed.
Per schemas/events.schema.json:
event_type is WORK-only (closed 10-value enum):
content_new, content_revise, content_remove, tech_fix, quickwin_applied, pillar_launch, schema_fix, redirect_deployed, backlink_outreach, manual (F-8 invariant). monitoring_completed
is NOT in the enum.
event_kind=audit requires audit_action + audit_target +
actor (allOf if/then conditional, lines per schema). It does
not carry event_type.
Therefore the worker writes:
event_kind=audit
audit_action="accessed" (enum: created/modified/deleted/accessed/
permission_changed/config_changed)
audit_target="reports:monitoring-weekly:{week_start}_{week_end}"
actor="agent:monitoring-weekly"
schema_version="1.0", event_id, timestamp, project_id
(envelope required across all kinds).
This mirrors the Phase 5 governance/drift-check pattern
(audit_action="accessed", audit_target="invariants:25",
actor="drift-check") — drift-check's audit-only convention is the
authority this skill reuses. Diverges from W-G1 (indexing-ping)
which used event_kind=work + event_type=manual + indexing_ping sub-object; that path requires a task_id mint and is reserved for
work-bearing skills. monitoring-weekly does no work — it only
reads + reports — so the audit kind is the semantic-correct choice.
Inputs (frontmatter contract)
| Name | Type | Default | Notes |
|---|
week_start | string | — | Required. YYYY-MM-DD inclusive window start. |
week_end | string | today | Inclusive window end. Default = run-time date.today(). |
Both inputs are validated as ISO-8601 dates before any I/O. Invalid
format raises MonitoringWeeklyValidationError (DURUR #0 envelope).
Outputs (artifacts produced — 2 entries, master.xlsx ABSENT)
_state/events.jsonl — single-row audit append (or 2 rows if
DURUR #5 MAD anomaly severity=RED fires; the second row carries
audit_action="accessed" + audit_target=...:anomaly + a notes
field flagging metric/direction/modified-z; severity is encoded
report-side, not via a schema field).
outputs/reports/{date}-monitoring-weekly.md — human-readable
health check report with 5 sections (exec_summary, drift_section,
gsc_anomaly_section, budget_burn_section, escalations).
master.xlsx is NOT in outputs[] — Phase 9 8-reporting-skill
no-write paterni reuse (cf. weekly-summary outputs[0]
master.xlsx#none confirm marker; this skill instead omits the entry
because R-WAVE-2 brief requires only 2 outputs).
DURUR (no fall-back) conditions — 5 sentinels
Stop and surface to the manager — do not patch, do not silently
swallow.
-
DURUR #1 — events.jsonl empty week range → SKIP.
When the events.jsonl filter for the window returns 0 rows, the
skill writes a single severity=info audit event with
audit_action="accessed" + audit_target="reports:monitoring- weekly:{week_start}_{week_end}:empty" and does NOT write the
markdown report. Report path resolves to a sentinel "empty window"
marker that the test suite asserts.
-
DURUR #2 — budget_credits_per_day absent in project-config
→ AMBER + default 500 credits/day fallback.
Wave-3 inline scope: PLACEHOLDER (deferred Phase 14+). The inline
runtime does not read project-config today, so this fallback is not
yet wired. When implemented: the report's budget_burn_section
carries the AMBER badge and a note that the baseline came from the
hard-coded fallback.
-
DURUR #3 — drift-check output unavailable (events filter on
event_kind=audit AND audit_target ~ invariants:* returns empty
in the window) → AMBER + report empty section.
The drift_section shows "drift-check henüz çalıştırılmamış" and
the report severity escalates to AMBER.
-
DURUR #4 — template path
templates/reports/monitoring-weekly.template.md not on disk →
AMBER + inline render fallback. The skill embeds an inline template
string as a defensive fallback (the body of this SKILL.md carries
the inline template definition under "Inline Template Fallback"
section below). The report renders, and the audit event records
the fallback path was used.
-
DURUR #5 — MAD GSC anomaly severity=RED → CRITICAL escalation.
Wave-1a inline scope: ACTIVE (GAP-M4 / R-141). Block 3 reads the
_state/metrics/gsc-weekly.jsonl ledger and runs
scripts.reporting.weekly_anomaly.detect() — the robust
median + MAD modified z-score (NIST/Iglewicz–Hoaglin,
M = 0.6745·(x − median)/MAD, flagged at |M| ≥ 3.5) gated by
percent + absolute floors over a trailing window of complete ISO
weeks. A flagged worsening of clicks / impressions / avg_position
yields severity RED; a ctr drop yields AMBER; an improvement
direction is INFO. When the anomaly severity is RED, the report's
escalations section is populated AND a second append_audit row is
written (audit_target="reports:monitoring-weekly:{week}:anomaly",
notes carrying metric / direction / modified_z).
Calendar guard (R-137): if the week overlaps a Google Ranking
update window (google-update-calendar.json, incl. a 7-day settling
buffer), the anomaly is capped at AMBER with an
attribution_caution — Google's own guidance is not to attribute
movement during/just after a rollout, so it is NOT escalated to a
second-row CRITICAL.
Insufficient history is NOT a DURUR. With fewer than 6 complete
ISO weeks the detector returns insufficient_history and the section
renders the honest points_used/6 string — no alarm, no second row,
severity unchanged from the drift/portfolio rollup. (The discredited
standard-deviation-on-n≈8 placeholder this replaces is described in the intro.)
Workflow (8 step)
- Read project-config for
budget_credits_per_day baseline + GSC
siteUrl. Missing key → DURUR #2 (default 500). Wave-3 inline
scope: PLACEHOLDER (deferred Phase 14+) — the inline runtime does
not open project-config; this step lands with the budget-burn
capability.
- Read events.jsonl with week range filter
(
week_start..week_end inclusive). 0 rows → DURUR #1 SKIP.
- drift-check output reuse — filter events on
event_kind=audit AND audit_target startswith "invariants:".
0 rows in window → DURUR #3 AMBER.
- GSC anomaly detect — Wave-1a inline scope: ACTIVE (GAP-M4 /
R-141). Block 3 reads
_state/metrics/gsc-weekly.jsonl (the
gsc-pull Step 7b ledger), derives current_iso_week from the
validated week_start, loads the Ranking-update calendar
(google-update-calendar.json engine seed ∪ shared/cache/...
workspace overlay) and computes the week's overlaps, then calls
weekly_anomaly.detect(records, current_iso_week, update_overlaps=...).
Severity rolls up max(drift/portfolio severity, anomaly severity).
RED → DURUR #5. Missing/sparse ledger → insufficient_history honest
render (no crash, no alarm).
- Budget burn rate — Wave-3 inline scope: PLACEHOLDER (deferred
Phase 14+). The current inline runtime reports a recent-events count
from
portfolio.json, not a computed burn rate. When implemented:
sum cost.credits from events.jsonl in window per day and compute the
daily_mean / budget_credits_per_day ratio (ratio > 1.0 → AMBER
badge; > 2.0 → RED badge).
- Report render —
templates/reports/monitoring-weekly.template.md
via string.Template $var substitution (Phase 1 mirası
scripts/reporting/render_template.py paterni reuse). Missing
template → DURUR #4 inline fallback.
- NO master.xlsx update — read-only aggregation. Phase 9 8
reporting skill no-write paterni reuse. The transform module never
imports
scripts.excel.transaction and never calls wb.save.
- events.jsonl append — single audit row (or 2 if DURUR #5
fires). Schema-first override applied per the section above.
Inline Orchestration (Phase B Wave 3 — Q-V1.2-MONITORING-WEEKLY-MISSING-SCRIPT-01 RESOLVED)
Skill body inline transform paterni (option b — thin orchestration, no
scripts/reporting/monitoring_weekly.py subprocess). 3 Python block
sequential helper exec compatible (rules/skills.md Section 1 enforce —
- block sys.path marker; rules/skills.md Section 3 multi-line format).
Block 1 — Setup + Read drift-check Output
import os
import sys
import json
from pathlib import Path
from datetime import datetime, timezone
from string import Template
sys.path.insert(0, os.getcwd())
project_slug = os.environ.get("PSEO_PROJECT_ID")
if not project_slug:
print("PSEO_PROJECT_ID env var required — orchestrator-injected at runtime")
sys.exit(0)
week_start = os.environ.get("MONITORING_WEEK_START", "")
week_end = os.environ.get("MONITORING_WEEK_END", "")
workspace_root_env = os.environ.get("PSEO_WORKSPACE_ROOT")
if workspace_root_env:
workspace_root = Path(workspace_root_env)
else:
workspace_root = Path.home() / "Documents" / "platinum-seo-workspace"
REPO_ROOT = Path.cwd()
consistency_path = (
workspace_root / "projects" / project_slug / "_state" / "cache" / "consistency-report.json"
)
if consistency_path.exists():
drift_data = json.loads(consistency_path.read_text(encoding="utf-8"))
red_count = drift_data.get("red_count", drift_data.get("fail_count", 0))
amber_count = drift_data.get("amber_count", 0)
green_count = drift_data.get("green_count", drift_data.get("pass_count", 0))
drift_verdict = drift_data.get("verdict", "UNKNOWN")
drift_available = True
else:
red_count = amber_count = green_count = 0
drift_verdict = "AMBER (drift-check henüz çalıştırılmamış)"
drift_available = False
Block 2 — Read portfolio.json + Aggregate Per-Project Metrics
portfolio_path = workspace_root / "shared" / "portfolio.json"
if portfolio_path.exists():
portfolio_data = json.loads(portfolio_path.read_text(encoding="utf-8"))
projects = portfolio_data.get("projects", [])
project_entry = next(
(p for p in projects if p.get("slug") == project_slug),
None,
)
if project_entry:
completion_pct = float(project_entry.get("completion_percentage", 0.0))
active_oq_count = int(project_entry.get("active_oq_count", 0))
recent_events = int(project_entry.get("recent_events_count_7day", 0))
portfolio_available = True
else:
completion_pct = 0.0
active_oq_count = 0
recent_events = 0
portfolio_available = False
else:
completion_pct = 0.0
active_oq_count = 0
recent_events = 0
portfolio_available = False
if red_count >= 5 or not drift_available:
severity = "RED" if red_count >= 5 else "AMBER"
elif amber_count > 0:
severity = "AMBER"
else:
severity = "GREEN"
Block 3 — Emit Audit Event + Render Markdown Report
template_path = REPO_ROOT / "templates" / "reports" / "monitoring-weekly.template.md"
INLINE_TEMPLATE = (
"---\n"
"project_id: $project_slug\n"
"period_start: $week_start\n"
"period_end: $week_end\n"
"generated_at: $generated_at\n"
"report_kind: monitoring_weekly\n"
"severity: $severity\n"
"---\n\n"
"# Monitoring Weekly — $project_slug\n\n"
"**Pencere:** $week_start – $week_end\n"
"**Genel severity:** $severity\n\n"
"## Exec Summary\n\n$exec_summary\n\n"
"## Drift Section\n\n$drift_section\n\n"
"## GSC Anomaly Section\n\n$gsc_anomaly_section\n\n"
"## Budget Burn Section\n\n$budget_burn_section\n\n"
"## Escalations\n\n$escalations\n"
)
if template_path.exists():
template_str = template_path.read_text(encoding="utf-8")
else:
template_str = INLINE_TEMPLATE
generated_at = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
from scripts.reporting import weekly_anomaly, update_calendar
from datetime import date as _date
ledger_path = (
workspace_root / "projects" / project_slug / "_state" / "metrics" / "gsc-weekly.jsonl"
)
ledger_records = []
if ledger_path.exists():
for _line in ledger_path.read_text(encoding="utf-8").splitlines():
_line = _line.strip()
if not _line:
continue
try:
ledger_records.append(json.loads(_line))
except json.JSONDecodeError:
continue
try:
_iso = _date.fromisoformat(week_start[:10]).isocalendar()
current_iso_week = f"{_iso[0]}-W{_iso[1]:02d}"
except (ValueError, TypeError):
current_iso_week = ""
engine_cal = REPO_ROOT / "google-update-calendar.json"
overlay_cal = workspace_root / "shared" / "cache" / "google-update-calendar.json"
update_overlaps = None
if engine_cal.exists() and week_start and week_end:
try:
_cal = update_calendar.load_calendar(
engine_cal, overlay_cal if overlay_cal.exists() else None
)
update_overlaps = update_calendar.overlaps(week_start, week_end, _cal)
except (OSError, ValueError, KeyError):
update_overlaps = None
anomaly = weekly_anomaly.detect(
ledger_records, current_iso_week, update_overlaps=update_overlaps
)
anomaly_sev = anomaly.get("severity", "none")
def _sev_rank(s):
return {"GREEN": 0, "none": 0, "INFO": 0, "AMBER": 2, "RED": 3}.get(s, 0)
if _sev_rank(anomaly_sev) > _sev_rank(severity):
severity = anomaly_sev
exec_summary = (
f"Haftalık sağlık özeti: drift={red_count}R/{amber_count}A/{green_count}G "
f"(verdict={drift_verdict}); completion={completion_pct:.1f}%; "
f"active_oq={active_oq_count}; recent_events_7day={recent_events}; "
f"gsc_anomaly={anomaly['status']}/{anomaly_sev}."
)
drift_section = (
f"Drift counts (consistency-report.json): RED={red_count} "
f"AMBER={amber_count} GREEN={green_count}. "
f"Verdict: {drift_verdict}. Available: {drift_available}."
)
if anomaly["status"] == "insufficient_history":
gsc_anomaly_section = (
"GSC anomali tespiti (median+MAD modified-z, R-141): yetersiz geçmiş — "
f"{anomaly['points_used']}/{anomaly['needed']} tam ISO hafta (≥6 gerekir). "
"Ledger biriktikçe aktifleşir (cold-start: gsc-pull days_back=112)."
)
elif anomaly["status"] == "current_week_missing":
gsc_anomaly_section = (
f"GSC anomali tespiti: {current_iso_week} ledger'da yok — gsc-pull bu "
"hafta için weekly ledger satırı yazmadı."
)
else:
_cells = []
for _m in ("clicks", "impressions", "ctr", "avg_position"):
_md = anomaly["metrics"].get(_m)
if not _md:
continue
_cells.append(
f"{_m}={_md['value']} (medyan {_md['median']}, z={_md['modified_z']}, "
f"bayrak={'EVET' if _md['flagged'] else 'hayır'}, yön={_md['direction']})"
)
_names = anomaly.get("anomalies") or "yok"
gsc_anomaly_section = (
f"GSC anomali (median+MAD, {anomaly['points_used']} hafta baz, R-141): "
f"severity={anomaly_sev}, anomaliler={_names}. " + " | ".join(_cells)
)
if anomaly.get("attribution_caution"):
gsc_anomaly_section += " ⚠ " + anomaly["attribution_caution"]
budget_burn_section = (
f"Recent events 7-day count: {recent_events} (portfolio.json available={portfolio_available}). "
"Budget burn rate calc Phase 14+ scope (events.jsonl cost.credits aggregation)."
)
_esc = []
if anomaly.get("severity") == "RED":
_det = "; ".join(
f"{_m} {anomaly['metrics'][_m]['direction']} "
f"(modified_z={anomaly['metrics'][_m]['modified_z']})"
for _m in anomaly.get("anomalies", [])
)
_esc.append(
f"CRITICAL (DURUR #5): GSC anomali RED — {_det} — ikinci audit satırı yazıldı."
)
if anomaly.get("attribution_caution"):
_esc.append("Dikkat: " + anomaly["attribution_caution"])
if not _esc:
_esc.append(f"Eskalasyon yok. Genel severity={severity}.")
escalations = " ".join(_esc)
variables = {
"project_slug": project_slug,
"week_start": week_start,
"week_end": week_end,
"generated_at": generated_at,
"severity": severity,
"exec_summary": exec_summary,
"drift_section": drift_section,
"gsc_anomaly_section": gsc_anomaly_section,
"budget_burn_section": budget_burn_section,
"escalations": escalations,
}
rendered = Template(template_str).safe_substitute(variables)
report_dir = workspace_root / "projects" / project_slug / "outputs" / "reports"
report_dir.mkdir(parents=True, exist_ok=True)
report_path = report_dir / f"{date_str}-monitoring-weekly.md"
report_path.write_text(rendered, encoding="utf-8")
from scripts.state import events_writer
events_writer.append_audit(
project_id=project_slug,
audit_action="accessed",
audit_target=f"reports:monitoring-weekly:{week_start}_{week_end}",
actor="agent:monitoring-weekly",
workspace_root=workspace_root,
notes=(
f"weekly_monitoring severity={severity} "
f"red={red_count} amber={amber_count} green={green_count} "
f"completion={completion_pct:.1f}% active_oq={active_oq_count} "
f"drift_available={drift_available} portfolio_available={portfolio_available}"
),
)
if anomaly.get("severity") == "RED":
_anote = "; ".join(
f"{_m}:{anomaly['metrics'][_m]['direction']}:"
f"z={anomaly['metrics'][_m]['modified_z']}"
for _m in anomaly.get("anomalies", [])
)
events_writer.append_audit(
project_id=project_slug,
audit_action="accessed",
audit_target=f"reports:monitoring-weekly:{week_start}_{week_end}:anomaly",
actor="agent:monitoring-weekly",
workspace_root=workspace_root,
notes=f"gsc_anomaly RED {_anote}",
)
print(f"monitoring-weekly report written: {report_path}")
print(f"audit event appended: project={project_slug} severity={severity}")
Schema-First Compliance
event_kind=audit — event_type field YASAK (rules/events-writer.md
Section 4c + Section 6).
audit_action="accessed" — read-only access trail (drift-check
doğum belgesi paterni reuse: Phase 5 governance audit kind).
audit_target namespace reports:monitoring-weekly:{week} —
cross-project audit query selectability.
events_writer.append_audit convenience wrapper — envelope
auto-populate (schema_version + event_id + timestamp + project_id);
bare append(event) API YASAK (rules/events-writer.md Section 2 +
Phase B Wave 1 fix).
Foundational Principles Enforcement (3-Layer)
The 3 üst-prensip (Phase 10 rules/content-quality.md#foundational- principles) gate this skill end-to-end. No alt-rule (R-01..R-148)
overrides them.
Principle 1 — Truth-Verifiable Health Report
Every datum in the report is sourced from a tangible artifact. Wave-1a
inline scope — what the runtime actually reads today:
drift_section ← _state/cache/consistency-report.json
(drift-check output: red/amber/green counts + verdict).
exec_summary ← computed roll-up of the drift counts +
shared/portfolio.json health fields (completion %, active OQ
count, recent-events count); no free-form fabrication.
gsc_anomaly_section ← _state/metrics/gsc-weekly.jsonl (the
gsc-pull Step 7b ledger) run through weekly_anomaly.detect()
(median + MAD modified-z, R-141) + the Ranking-update calendar
(google-update-calendar.json, R-137). With <6 complete weeks it
renders the honest insufficient_history string — never a fabricated
delta. The discredited standard-deviation-on-n≈8 placeholder is gone.
escalations ← computed from the anomaly result (RED ⇒ a second
audit row; calendar overlap ⇒ AMBER cap + attribution caution).
ONLY still deferred to Phase 14+ (PLACEHOLDER string):
budget_burn_section ← will aggregate events.jsonl cost.credits
(Phase 7+8 work events). Today it reports a recent-events count from
portfolio.json.
The skill never invents values; the GSC section reports computed
robust statistics or honestly announces insufficient history. AI
suistimal yasağı: hayali delta fabrikasyonu YASAK — the GSC path reads
the ledger, never guesses.
Principle 2 — Profile-Aware Severity
The severity thresholds adapt to project-config.profile:
ymyl (Your Money Your Life): drift-check FAIL → CRITICAL
escalation immediately (compliance burst alert; one FAIL is one
too many for medical/legal/financial sites).
e-commerce: GSC clicks delta < -20% week-over-week → AMBER
(conversion-loss signal); drift-check FAIL → AMBER.
b2b-saas: GSC impressions delta < -30% AND signup_velocity
proxy (events.jsonl event_type=content_new count) drop → AMBER
(top-of-funnel signal).
local-service / portfolio: drift-check FAIL only →
AMBER (lower volume, lower stakes).
The 5-value profile enum lives in
schemas/project-config.schema.json (Phase 11 W-A1 v1.2 cascade
authority): e-commerce, ymyl, local-service, b2b-saas,
portfolio.
Principle 3 — Anti-Cheap-Content (no fabrication)
The skill renders ONLY counts + factual deltas. It does NOT generate
prose summaries via LLM, does NOT invent week-over-week percentages,
and does NOT guess at root causes. The exec_summary is a
rule-based 1-2 sentence Turkish rollup composed from the section
counts (template string.Template substitution).
Inline Template Fallback (DURUR #4)
When templates/reports/monitoring-weekly.template.md is absent, the
transform falls back to an inline template string defined in Block 3
of this SKILL.md (the INLINE_TEMPLATE constant inside the inline
orchestration block; see line ~315). The fallback template carries the
same 5 sections + same $var slots as the on-disk template. The audit
event records template_path=inline in the note field. The test suite
asserts both render paths produce structurally equivalent output.
(Q-V1.2-MONITORING-WEEKLY-MISSING-SCRIPT-01 RESOLVED via option b —
no separate scripts/reporting/monitoring_weekly.py exists; the
constant lives inline alongside the orchestration blocks.)
Cross-references
- Schemas:
schemas/events.schema.json (audit event_kind required
fields: audit_action + audit_target + actor),
schemas/master-excel.schema.json (gsc_performance sheet
read-only access), schemas/skill-frontmatter.schema.json (this
frontmatter).
- Cross-modules (READ-only, IMPORT pattern):
scripts/reporting/render_template.py (string.Template $var
rendering reuse).
- Reference SKILL.md:
skills/reporting/weekly-summary/SKILL.md
(Phase 9 weekly aggregation paterni — local aggregator + READ-ONLY
contract on master.xlsx) and
skills/reporting/portfolio-overview/SKILL.md (Phase 9 8
reporting skill no-write paterni — strict read-only aggregator).
- Reference governance skill:
skills/governance/drift-check/SKILL.md
(Phase 5 audit event_kind paterni: audit_action=accessed + audit_target=invariants:25 + actor=drift-check).
- Template:
templates/reports/monitoring-weekly.template.md
(DURUR #4 fallback to inline string if absent).
- Tests:
tests/skills/test_monitoring_weekly.py.
Discipline checklist