Skip to content
Back to skills

Portfolio Overview

ASecurity

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 statu...

  • 27 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 2, 2026
ai-agentspythongo

Works with

  • mcp

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add popiliadam/platinum-seo-engine --skill portfolio-overview --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Portfolio Overview?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Portfolio Overview
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/popiliadam-portfolio-overview/badge)](https://www.skillsdirectory.com/skills/popiliadam-portfolio-overview)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: portfolio-overview
description: |
  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).
version: "1.0"
status: active
category: reporting
inputs:
  portfolio_root:
    type: string
    required: false
    description: "Path to portfolio workspace root. Default: $PSEO_PORTFOLIO_ROOT, $PSEO_WORKSPACE_ROOT, or .pse-workspace marker discovery."
  filter_active:
    type: boolean
    required: false
    default: true
    description: "Iterate active_projects only (default true). pending_onboard NEVER read per schema description."
outputs:
  - "master.xlsx#none"
  - "outputs/reports/{date}-portfolio-overview.md"
  - "inbox/local/{date}-portfolio-overview.json"
consumes:
  - "portfolio-init:projects/_portfolio/portfolio.config.json"
  - "dashboard-refresh:master.xlsx#dashboard"
  - "master-task-sync:master.xlsx#master_task"
produces:
  - "weekly-summary"
  - "portfolio-weekly-brief"
  - "monthly-report"
triggers:
  manual: []
  natural_language: |
    "portföy özet", "tüm projeler", "portfolio overview",
    "multi-project status", "portföy durumu", "active projects özet",
    "tüm projelerin durumu"
  hooks: []
mcp_tools:
  required: []
  optional: []
budget:
  uses_paid_mcp: false
  estimated_credits: 0
autonomy:
  confidence: HIGH
  requires_approval: false
  safe_auto_execute: true
---

# portfolio-overview — reporting skill (Phase 9 Wave 1)

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.

## Inputs (frontmatter contract)

| 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 (artifacts produced)

- `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).

## Sources consumed (per active project)

| # | 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.

## Aggregation logic

```
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).
```

## Idempotency contract

> **Re-run with identical workbook state → byte-identical snapshot
> + report.**

Mechanically:
1. Snapshot ordering is deterministic (priority, slug).
2. Totals tuple is fixed at module scope.
3. JSON output uses `sort_keys=True` + `indent=2`.
4. Markdown template substitution is idempotent.

## DURUR conditions

Stop and flag the manager — do not patch, do not fall back.

1. **PortfolioConfigMissingError** — `portfolio.config.json` absent /
   unreadable. Run portfolio init first.
2. **PortfolioConfigInvalidError** — payload failed Draft 7 validation
   against `schemas/portfolio-config.schema.json`. Schema-first violation.
3. **ActiveProjectsCeilingError** — `active_projects` > 12 (schema
   `maxItems` sentinel). Move surplus to `pending_onboard`.
4. **ReadOnlyContractViolation** — `cross_query.read_only != true`
   (schema `const: true`). The aggregator cannot run with read-only
   disabled.
5. **WorkspaceRootUnsetError** — could not resolve `portfolio_root`
   from arg / env / `.pse-workspace` marker.

(Per-project missing `master.xlsx` is **NOT** a DURUR — graceful skip
with warning, snapshot still emitted.)

## Audit Event Emit (Q-RP-01 RESOLVED 2026-05-06 Phase B post-closeout)

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.

```python
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})",
)
```

## Cross-references

- Schemas: `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).
- Cross-modules (IMPORT-only): `scripts/reporting/render_template.py`
  (`string.Template` $var rendering convention).
- Transform: `scripts/reporting/portfolio_overview.py`.
- Template: `templates/reports/portfolio-overview.template.md`.
- Tests: `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).
- Pattern reference: `scripts/planning/master_task_sync.py` (Phase 8
  W-D1 local aggregator pattern).

## Discipline checklist

- [x] TODO/fallback YASAK — every DURUR raises, none silently downgrade.
- [x] Schema-first — frontmatter validates against
      `schemas/skill-frontmatter.schema.json` Draft 7. Every config
      payload checked against `portfolio-config.schema.json` Draft 7.
- [x] Plugin-agnostik — no slug literals; `active_projects` iteration
      drives every path; transform has 0 hardcoded slug words.
- [x] ADR-013: `Use when` / `Also use when` / `Do not use when` are
      STRING content inside `description`, not separate fields.
- [x] Cross-module IMPORT discipline — `render_template.py` convention
      reused via `string.Template` inline; no module imported / mutated.
- [x] D-003 helper IMPORT NOT applicable — local aggregation, no DFS
      payload consumed.
- [x] F1: write target is **NOTHING** (read-only aggregator).
- [x] F5: `outputs.*` values are STRING-TYPED (artifact paths or
      stringified counts), never raw ints.
- [x] Append-only state — `events.jsonl` NOT written (Phase 9 W1
      convention; Q-RP-01 deferred). Snapshot JSON is overwrite-safe
      because filename includes `{date}`.
- [x] READ-ONLY contract — no `.save(`, no `transaction.append(`,
      no `transaction.update(`, no `transaction.delete(` call sites
      in the transform module (verified by `assert_read_only_module()`).
- [x] cross_query.read_only=true (schema const) honored.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.