From platinum-seo-engine
Use when: kullanıcı "portföy özet", "tüm projeler", "tüm projelerin durumu", "portfolio overview", "multi-project status", "portföy durumu", "active projects özet" der ya da portföy genelinde KPI karşılaştırması istediğinde tetiklenir. Also use when: portfolio.config.json `active_projects` listesi doluyken (1-12 entry, schema maxItems=12); her aktif projenin master.xlsx'i mevcut (eksikler graceful skip + warning); tek bir pass'te tüm aktif projelerin dashboard KPI snapshot + master_task status karşılaştırması raporlanır; weekly-summary ya da portfolio-weekly-brief öncesinde portfolio-wide tablo gerekiyor. Do not use when: portfolio.config.json yok (portfolio init önce çalışmalı, DURUR PortfolioConfigMissingError); active_projects 12'yi aşıyor (schema maxItems sentinel, DURUR ActiveProjectsCeilingError — fazla entry'leri pending_onboard'a taşı); cross_query.read_only != true (schema const, DURUR ReadOnlyContractViolation); tek bir proje detayı isteniyorsa (whats-next ya da master-task-sync skill'i kullan, bu skill çoklu proje aggregate eder); workbook'a YAZILACAK bir şey varsa (FORBIDDEN — bu skill strict read-only aggregator).
How this skill is triggered — by the user, by Claude, or both
Slash command
/platinum-seo-engine:portfolio-overviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Multi-project READ-ONLY aggregator. Iterates portfolio.config.json
Multi-project READ-ONLY aggregator. Iterates portfolio.config.json
active_projects (max 12, schema-enforced) and pulls each project's
master.xlsx#dashboard KPI cells + locally-computed master_task
status counts into a single portfolio overview snapshot + markdown
report. No MCP, no DFS, no budget pre-flight, no Excel
write — strict read-only.
This skill follows the convention authority established by
skills/planning/master-task-sync/SKILL.md (Phase 8 W-D1 — local
aggregator pattern: aggregate transform module, drift-recovery JSON
snapshot, markdown report). The protocol shape, raw envelope discipline,
and DURUR + flag rule are reused — only the source (multi-project read
instead of single-project local sheets) and the output discipline (no
master.xlsx mutation, no events.jsonl) change.
Per schemas/portfolio-config.schema.json#cross_query.read_only
(const: true, schema lines 90-91), portfolio_overview is a strict
read-only aggregator. The transform module enforces this defensively:
no wb.save(), no transaction.append(), transaction.update(), or
transaction.delete() call sites; load_workbook(read_only=True) on
every workbook read. The assert_read_only_module() helper greps the
source for forbidden write tokens — used by the test suite as a
schema-first guard.
| Name | Type | Default | Notes |
|---|---|---|---|
portfolio_root | string | env | Workspace root; falls back to $PSEO_PORTFOLIO_ROOT, $PSEO_WORKSPACE_ROOT, or .pse-workspace marker. |
filter_active | boolean | true | Iterate active_projects only. pending_onboard NEVER read (schema description). |
outputs/reports/{date}-portfolio-overview.md — markdown report
(multi-project table + aggregate totals); rendered via string.Template
per scripts/reporting/render_template.py convention.inbox/local/{date}-portfolio-overview.json — drift-recovery snapshot
containing every per-project KPI + status_count + warnings list.master.xlsx#none — declarative READ-ONLY confirmation (no sheet
written across any iterated project).No events.jsonl entry. Phase 9 Wave 1 convention; portfolio-wide
provenance governance refinement is deferred to Q-RP-01 (closeout).
| # | Source | Read mode |
|---|---|---|
| 1 | portfolio.config.json (root) | json |
| 2 | master.xlsx#dashboard (R10, R47-R52, R59) | openpyxl read_only=True |
| 3 | master.xlsx#master_task (col J) | openpyxl read_only=True |
The 8 dashboard KPI cells are pulled verbatim per
schemas/master-excel.schema.json#dashboard required_cells:
R10=total_pillars, R47=master_task_total, R48=master_task_done,
R49=master_task_todo, R50=master_task_ongoing,
R51=cannibalization_count, R52=quick_wins_count,
R59=last_audit_date. master_task statusEnum counts are computed
locally by scanning column J — used for a drift cross-check against
R47-R50.
1. Resolve portfolio_root (arg → env → .pse-workspace).
2. Read portfolio.config.json + jsonschema validate (Draft 7).
3. For each active_projects entry:
- resolve master.xlsx path (workspace_path/projects/slug/master.xlsx).
- if missing: emit warning, append empty snapshot (graceful skip).
- else: read 8 dashboard cells + scan master_task col J.
- cross-check dashboard R47-R50 vs locally-computed totals;
set status_check_drift=True on mismatch.
4. Sort snapshots by (priority asc, slug asc) — deterministic.
5. Sum per-project KPIs into batch.totals.
6. Render markdown report via string.Template substitution.
7. Write snapshot.json + report.md (no master.xlsx writes).
**Re-run with identical workbook state → byte-identical snapshot
- report.**
Mechanically:
sort_keys=True + indent=2.Stop and flag the manager — do not patch, do not fall back.
portfolio.config.json absent /
unreadable. Run portfolio init first.schemas/portfolio-config.schema.json. Schema-first violation.active_projects > 12 (schema
maxItems sentinel). Move surplus to pending_onboard.cross_query.read_only != true
(schema const: true). The aggregator cannot run with read-only
disabled.portfolio_root
from arg / env / .pse-workspace marker.(Per-project missing master.xlsx is NOT a DURUR — graceful skip
with warning, snapshot still emitted.)
Schema-first override Section 4c paterni reuse (drift-check Phase 5 doğum belgesi). event_kind=audit row append per rules/events-writer.md Section 4c — event_type field YASAK per Section 6 disambiguation.
import os
import sys
from pathlib import Path
sys.path.insert(0, os.getcwd())
project_slug = os.environ.get("PSEO_PROJECT_ID")
if not project_slug:
print("PSEO_PROJECT_ID not set — audit event skip")
sys.exit(0)
report_date = os.environ.get("REPORT_DATE", "2026-05-06")
workspace_root_env = os.environ.get("PSEO_WORKSPACE_ROOT")
workspace_root = (
Path(workspace_root_env) if workspace_root_env
else Path.home() / "Documents" / "platinum-seo-workspace"
)
from scripts.state import events_writer
events_writer.append_audit(
project_id=project_slug,
audit_action="accessed",
audit_target=f"reports:portfolio-overview:{report_date}",
actor="agent:portfolio-overview",
workspace_root=workspace_root,
notes=f"local_aggregation report-only (portfolio-overview; date={report_date})",
)
schemas/portfolio-config.schema.json (v1.1 —
ActiveProjectEntry required fields slug + workspace_path + profile +
priority; active_projects.maxItems = 12;
cross_query.read_only = true const),
schemas/master-excel.schema.json#dashboard
(required_cells 8 KPI cells + forbidden_patterns no-formula rule),
schemas/master-excel.schema.json#master_task
(required_columns 19 cols + #/definitions/statusEnum),
schemas/skill-frontmatter.schema.json (this frontmatter).scripts/reporting/render_template.py
(string.Template $var rendering convention).scripts/reporting/portfolio_overview.py.templates/reports/portfolio-overview.template.md.tests/skills/test_portfolio_overview.py (6-8 cases incl.
schema validate + maxItems sentinel + missing workbook tolerance +
read-only enforcement + natural_language length + forbidden tokens
guard).scripts/planning/master_task_sync.py (Phase 8
W-D1 local aggregator pattern).schemas/skill-frontmatter.schema.json Draft 7. Every config
payload checked against portfolio-config.schema.json Draft 7.active_projects iteration
drives every path; transform has 0 hardcoded slug words.Use when / Also use when / Do not use when are
STRING content inside description, not separate fields.render_template.py convention
reused via string.Template inline; no module imported / mutated.outputs.* values are STRING-TYPED (artifact paths or
stringified counts), never raw ints.events.jsonl NOT written (Phase 9 W1
convention; Q-RP-01 deferred). Snapshot JSON is overwrite-safe
because filename includes {date}..save(, no transaction.append(,
no transaction.update(, no transaction.delete( call sites
in the transform module (verified by assert_read_only_module()).npx claudepluginhub popiliadam/platinum-seo-engine --plugin platinum-seo-engineUse when: kullanıcı "haftalık portföy", "portfolio weekly", "tüm projeler haftalık", "haftalık brief", "weekly brief", "portföy haftalık raporu", "active_projects haftalık özet" der ya da cadence.weekly_brief.day cron tetiklenir. Also use when: portfolio.config.json v1.1 mevcut + active_projects doldurulmuş; her proje için master.xlsx + _state/events.jsonl ulaşılabilir; haftalık 7 günlük delta + last_sync_at freshness rapor olarak istenir; tek bir slug değil PORTFÖY ÇAPINDA özet beklenir; READ-ONLY agregasyon yeterli (yazma kapsamı YOK). Do not use when: portfolio.config.json yokken (init-portfolio önce çalışmalı, DURUR PortfolioConfigSchemaError); tek proje weekly istenirse (weekly-summary skill'ine yönlendir, bu skill PORTFÖY scope); aylık dökümle karıştırma (monthly-report skill'i ayrı); master.xlsx writer çağrısı isteniyorsa (FORBIDDEN — bu skill 100% READ-ONLY, hiçbir master_task hücresine yazmaz).
This skill should be used when a partner or consultant wants a readable snapshot of a cogni-projects portfolio for a partner meeting — staffing coverage per project, at-risk projects, and portfolio value by strategic impact — rather than reading raw entity files. Trigger on: "projects dashboard", "portfolio dashboard", "partner-meeting dashboard", "show me the project portfolio", "portfolio health", "staffing coverage", "which projects are at risk", or any request to review the project portfolio at a glance — even if the user does not say "dashboard" explicitly.
Resumes portfolio projects by discovering project state, surfacing progress, and recommending next steps. Useful for multi-session portfolio work.