Weekly Status Roll-Up Workflow
Role
You produce the weekly executive summary across all active projects in the PMO portfolio. This is the document that goes to leadership, steering committees, and cross-functional stakeholders. It synthesizes the week's daily status updates, tracker changes, and milestone progress into a single cohesive narrative.
After producing the summary, you write back the synthesized health data to PORTFOLIO.md, keeping the portfolio dashboard current for downstream consumers (daily-status, project- initiator, visualizations).
You are not summarizing transcripts or analyzing artifacts — that was done during the week by the PPM Agent and daily status workflow. You are rolling up the results.
Inputs
Read these files in order before generating:
- PORTFOLIO.md — List of all active projects with governance models and key dates
- For each active project (every item below is a tracked-layer read — see the read-side
aggregation contract that follows):
a. PROJECT.md — Current phase, milestones, health status
b. Daily Status Log — this week's
DEC-###/ACT-###entries (Monday through current day) c. Daily Status Log carry-forward — the openDEC-###/ACT-###entries carrying current blockers, decisions, and actions d. Communications Tracker —MSG-##rows for key communications this week (escalations, exec messages) e. RAID entries — Any new or updated risk/issue rows from this week - GitHub Issues — Any improvement proposals created this week:
gh issue list --label "improvement" --json number,title,createdAt --created ">YYYY-MM-DD"(where date = 7 days ago)
Read-side aggregation contract (tracked layer only). This roll-up aggregates from the
maintained tracked (Domain-B) layer — the DEC-### / ACT-### / MTG-### tracker entries and the
RAID rows — and never re-scans raw transcripts to re-derive them. The tracked layer is
trust_category: controlled-truth, and every extracted entry already carries its provenance
back-link: source_inputs on markdown-tracker entries, source_ref on RAID rows, each resolving to
the TR-### / MSG-### / source file the entry was extracted from. The declared inputs above are
therefore tracker entries plus those back-links, never the raw evidence behind them.
- Cite provenance; do not re-derive it. When a roll-up line must show where a decision, action,
or risk came from, resolve and cite that entry's
source_inputs/source_ref— do not open the transcript and re-read it. - A missing entry is a tracked-layer gap, not a licence to re-scan. When an item is absent from
the tracked layer, surface it as a gap for
tracker-managerto add on the write side; do not reconstruct it from raw evidence inside the roll-up. - Why: re-deriving a roll-up from raw evidence bypasses the controlled-truth layer and
re-introduces the un-cited, un-provenanced aggregation that the raw→tracked bridge exists to
eliminate. Write-side maintenance of the layer belongs to
tracker-manager; read-side enforcement is this skill's responsibility. The governing definition is the Aggregation source-of-truth rule in the Raw→Tracked Provenance section ofcore/schemas/tracker-schemas.md.
Reference docs
This skill consumes governed reference docs by role-name — it does not restate their content (duplicate-source-discipline; each doc owns its definitions). The Section 7 (Portfolio Governance) sub-blocks and the Section 1 dominance check below cite these by role:
| Reference | Owner / module | Consumed by | What this skill reads from it |
|---|---|---|---|
metric-registry.md |
this skill (weekly-status-rollup) — intra-module |
Section 1 health logic + Section 7 per-metric decision-rule validation + lag/lead audit | The cross-level metric → RAG-band → WHEN…THEN… decision-rule index. Each reported metric cites its governing rule verbatim from the registry row; this skill follows REFERENCED rows to their owning doc (channel-formats.md, capacity-model.md, backlog-health.md) for the live band rather than re-deriving thresholds. |
watermelon-detection.md |
pmo-qa-auditor — core module (via-public-api) |
Section 7 Watermelon Scan + the Section 1 dominance feedback | The canonical home of the 8-signal watermelon set (W1–W8) with severity tiers, false-positive filters, and the verdict-composition rule. This skill runs the signals by reference — it does not fork or restate them. The operations → core direction is the sanctioned cross-module flow enumerated in operations/README.md § Cross-Module Dependencies (markdown-doc-link reference per ADR-007; cross-module consumption posture per ADR-028). |
capacity-model.md |
delivery-engine — intra-module (operations) |
Section 7 Capacity Dashboard synthesis | The §1 effective-capacity formula and §9 Demand-Supply Gap RAG bands. The cross-project capacity view aggregates per-project Capacity Utilization (whose registry row already references this doc) into a portfolio view; it does not restate the formula or bands. |
Output Structure
Any roll-up artifact persisted to
08-Generated/is named per the artifact naming standard (../../../core/standards/artifact-naming-standard.md:_segment separator,--joined one-segment type slug from the controlled vocabulary, optional trailing ISO-8601 date, lowercase extension); versioning/status/lineage stay in frontmatter, never the filename.
Section 1: Portfolio Health Dashboard
A quick-reference table covering all active projects:
| Project | Phase | Health | Sprint/Milestone | Days to Next Gate | Key Risk |
|---------|-------|--------|-----------------|-------------------|----------|
| [Name] | [Phase] | 🟢/🟡/🔴 | [Sprint X / Phase Y] | [N] | [One-line] |
Health color logic:
- 🟢 GREEN: On track, no active blockers, milestone dates holding
- 🟡 YELLOW: At risk — active blockers exist but mitigation in progress, or timeline pressure without confirmed slip
- 🔴 RED: Blocked or slipped — confirmed timeline impact, unresolved escalations, or critical path broken
Section 2: Per-Project Summary
For each active project, generate:
[Project Name] — [Phase] — [Health Color]
This Week:
- 3-5 bullet points covering what happened this week (from daily status updates)
- Focus on outcomes and movement, not activity descriptions
- Include specific numbers where available (bugs resolved, tests passed, decisions made)
Key Risks & Blockers:
- Active blockers from carry-forward (with age in business days)
- New risks identified this week
- Escalations in progress
Decisions Made This Week:
- Decisions closed (from DEC-### entries that moved to MADE status)
- Include decision-maker and impact
Decisions Pending:
- Open DEC-### entries with deadlines
- Overdue blocking-decision escalation (thresholded + routed). For each open
DEC-### entry, compute the overdue clock
today − Deadlinein business days (carries[INFERRED: today − Deadline]; the deadline-keyed clock per../ppm-agent/references/proactive-follow-up-tracking.md§Aging "starts from the deadline date"). The escalation fires only for blocking-class decisions (the entry'sblocking: truefield — go/no-go, launch-sequence, and similar gating decisions). Apply the two-stage, due-date-keyed ladder:- WARN at
> 3 business dayspast due — emit a[RECOMMENDED]nudge to the decision-maker in the rollup output. No tier change (parallel to the Stale-RAID Warning band). - ESCALATE at
> 5 business dayspast due — emit an escalation action that bumps the decision one tier up the existing routing ladder in../ppm-agent/references/escalation-thresholds.md§2 (Team → Project → Program → Program-Critical/Sponsor → Portfolio). The escalate action names the decision, the decision-maker, the breached5bdthreshold, and the routed tier. This consumes the existing tier ladder by reference — it does not author a parallel tier scheme. - Coverage gap on absent
blocking: a DEC-### entry with noblockingfield → treat as non-blocking (no escalation) and flag the missing classification as a coverage gap on first encounter; never silently default to blocking. - Cross-skill ownership (mirrors the Stale-RAID split): this skill surfaces the
overdue-decision escalation in the roll-up;
ppm-agent(which owns DECISION escalations) is the router;delivery-engineMode G is where the decision artifact is updated. See the OPERATIONS.md Overdue-Decision Escalation Protocol. Reversibility CHEAP / recommend-tier — a flag + routed tag the operator reviews; never auto-decides the decision or mutates the tracker without approval (carry the tier per § Reversibility Discipline).
- WARN at
Next Week Focus:
- Top 3 priorities for next week
- Upcoming milestones or deadlines
- Required actions or decisions
Dual-Framing Bridge (conditional):
Only include when PROJECT.md has dual_framing_enabled: true.
Agile Track: [Sprint progress, velocity, backlog health]
Waterfall Track: [Milestone status, phase gate progress, deliverable status]
Both tracks converge on: [single unified priority or action]
Section 3: Cross-Project Items
- Dependencies between projects
- Shared resource conflicts
- Items that affect multiple projects
Section 3.6: Cross-Project RAID Aggregation (S6 fill logic)
The cross-project items above are rolled up into the composed ## Cross-Project RAID
portfolio section (S6, staged in Section 6) as a ranked, passive-voice-free risk view. S6 is
contract-driven: the aggregation reads the three cross-project risk fields of the
portfolio write-back contract §4
(S6) — it never re-derives them and never hand-types a risk list — so the deterministic
composer renders the rows from fields, not from agent-synthesized prose. This sub-block defines
the 3-leg source union and the per-leg row projection that FILLS the S6 shell (whose columns,
placement, and empty-state are defined in Section 6); it does not author a parallel cross-project
risk section — S6 is the single cross-project risk surface.
3-leg source union — aggregate the project-scoped leg, surface the two portfolio-tier legs:
| Leg | Contract field (backing entity) | Read filter — risk-bearing states only | Aggregate vs. surface |
|---|---|---|---|
| 1 | top_risks[] — RAID Item (project-scoped [Project]/) |
lifecycle_state ∈ {open, in-progress, mitigating} AND (severity High OR cross-project impact) |
aggregate — roll each project's active RAID up to the portfolio view |
| 2 | key_dependencies[] — Cross-Project Dependency / XPD (portfolio projects/_config/) |
state ∈ {open, broken} (a satisfied / waived dependency is not a live risk) |
surface — already portfolio-tier |
| 3 | cross_project_conflicts[] — Cross-Project Resource Conflict / XRC (portfolio projects/_config/) |
state ∈ {detected, acknowledged} (a resolved conflict is not a live risk) |
surface — already portfolio-tier |
The resource-conflict leg reads the cross_project_conflicts[] contract field (not the
entity directly), so all three legs are contract fields and S6 renders fully from the contract —
the composer stays deterministic and no S6 row is agent-synthesized.
Per-leg row projection → the S6 shell columns (Type · Item · Owner · Mitigation · Source-Tier · Projects-Affected):
| Shell column | Leg 1 — top_risks[] (RAID) |
Leg 2 — key_dependencies[] (XPD) |
Leg 3 — cross_project_conflicts[] (XRC) |
|---|---|---|---|
| Type (R/A/I/D) | RAID raid_type |
D (dependency) |
R (resource-contention risk) |
| Item (risk) | RAID summary + impact (what is at stake) |
{from} → {to} dependency is {state} |
{conflict} — resource over-allocated across the competing projects |
| Owner | RAID owner_person_id → Person |
depended-on project lead / recorded dependency owner | resource manager resolving the contention |
| Mitigation | RAID action_plan |
resolution path (satisfy / waive / escalate) | reallocation / sequencing plan |
| Source-Tier | Project |
Portfolio |
Portfolio |
| Projects-Affected | the sourcing project | {from} + {to} projects |
projects_affected[] |
Source-Tier is the escalation-ladder tier defined by the S6 shell (Team → Project → Program →
Program-Critical/Sponsor → Portfolio), seeded by each entity's storage tier: a project-scoped RAID
roll-up starts at Project (escalating per its severity), a portfolio-tier dependency/conflict at
Portfolio.
Aggregation rules (bind the fill):
- Rank:
severitydescending, thenimpact(the queryable key) — highest-signal risks first, not an unordered dump. - Passive-voice-free (hard gate): every S6 row carries all three of {risk, owner, mitigation}. A row whose contract field lacks an owner or a mitigation renders
[DRIFT: incomplete risk record — <field> missing](a repair flag) — never a passive "a risk exists" / "is being monitored" statement (CLAUDE.md § Guardrails, "No passive risk voice"). - ≥ 3 cross-component risk categories: the 3 legs ARE the categories — timeline contention (open / broken dependencies + RAID schedule risks), shared bottlenecks (resource over-allocation), and cross-project / vendor dependency risk (dependencies + RAID
Dependency-type items). - Sourced, not hand-typed: the population reads the authoritative RAID / XPD / XRC records through the contract fields, so the profile stays current — there is no hand-maintained risk list.
- Staleness: consumes the single
last_published/[STALE]marker owned by the contract (§3); a field aged past cadence renders[STALE]— no parallel freshness field. - Dedup: a cross-project risk appears in S6 only; the per-project S5 (
### Top Risks) references it withsee Cross-Project: [item](the existing "cross-project items live in Section 3 only" convention). S6 (risk-roll-up lens: risk / owner / mitigation) and S7 / S8 (state-register lens: from / to / state; person / projects / pct) are distinct lenses on the same entities, not duplicated content.
Scope boundary (methodology-neutral): this produces the neutral rolled-up rows only. The PMI
"Risk Profile" presentation a methodology pack renders on top of these rows is out of scope
here — owned by the portfolio-framework methodology pack, not this aggregation. (Boundary scope: this excludes the methodology-pack presentation layer only; reading delivery_approach to project neutral kinds/fields is done per the OPERATIONS.md Methodology Awareness Protocol and is distinct from the presentation the pack owns.)
Section 3.x: Cross-Project Correction Recurrence
Detect a behavioral correction recurring across projects — a redirect that is not
project-specific after all, but a latent platform guardrail. This is the spatial
recurrence axis (same correction active in ≥2 projects now), complementary to the
temporal axis owned by OPERATIONS.md § CORRECTIONS Graduation & Expiry Protocol
(a correction that has driven ≥2 course-corrections over time). This sub-block detects
the signal and routes it into that existing intake path — it does NOT author a
parallel improvement.yml mechanism.
Procedure (per weekly run):
- Enumerate each active project's
[Project]/CORRECTIONS.md(best-effort; a project with no file contributes zero entries — never read absence as a signal). - Tag each correction with its
(domain, theme)tuple using the two-pass heuristic in../../../core/disciplines/decision-discipline.md§4.3 (cited, not restated). - Group corrections by
(domain, theme)across projects. A group whose entries span ≥2 distinct projects fires as a cross-project recurrence candidate (the canonical N=2 emergence number perdecision-discipline.md§4.2, applied to the project-count axis — same number, not a new threshold). - Emit an actionable candidate (never a bare count):
{ what recurs — the (domain,theme) + representative correction text · which projects — the ≥2 project names + the entry from each · proposed guardrail — a one-line candidate governance rule }. - Route via the intake path — surface the candidate in Section 3 output AND log it
as a CORRECTIONS-graduation candidate for the Pattern Review pipeline
(
OPERATIONS.md § CORRECTIONS Graduation & Expiry ProtocolRule 3 field-mapping).release-plannerMode D drafts theimprovement.yml; the operator renders PROMOTE / KEEP / EXPIRE. This roll-up never files the issue itself (preserves the LITERAL-body operator gate and the human-in-the-loop write posture).
Single-project rule (no false positive): a (domain, theme) group whose entries all
come from one project has project-span 1 < 2 → does NOT fire. A correction unique to
one project produces no cross-project candidate ("a single instance is data, not pattern").
Reversibility: the candidate is a decision-class output — carry a reversibility tier + confidence per § Reversibility Discipline (an unpromoted candidate surfaced for operator review is CHEAP; a guardrail acted on downstream escalates per the tier table).
Single-project portfolio note: when only one project is active this sub-block is a no-op (no ≥2-project span possible) — omission is the correct signal, not a gap.
Section 4: Process Health
- File Router performance this week (files classified, misclassifications corrected)
- Tracker Manager stats (updates applied, rejected, evidence gate blocks)
- Unclassified queue status (items pending, age)
- Improvement proposals submitted (from GitHub Issues with
improvementlabel created this week)
Section 5: Looking Ahead (2-Week View)
- Milestones in the next 14 calendar days (across all projects)
- Required decisions with deadlines
- Scheduled meetings (SteerCo, phase gates, reviews)
- Resource or scheduling conflicts
Section 6: Portfolio Write-Back
After producing the executive summary (Sections 1-5), update PORTFOLIO.md with the synthesized data. This step keeps the portfolio dashboard current without manual intervention.
Consume the per-project rollup entity (do not re-derive). For each active project,
ppm-agent emits a [Project]_Rollup.md composed rollup entity per the portfolio write-back
contract (../../../core/standards/portfolio-writeback-contract.md) — a 7-field
per-project publishing schema (status, top_risks[], key_dependencies[], capacity_signal,
milestone_delta, cross_project_conflicts[], last_published). This section CONSUMES those
fields and composes the PORTFOLIO.md sections (the contract's S1–S8 section-schema map) from
them rather than re-deriving each field. In production the deterministic composer is invoked
with --as-of=today; it honors the [STALE] marker — a field whose age (today − last_published,
business days) exceeds 3 bd renders [STALE] inline, and > 5 bd auto-degrades. The one
staleness mechanism lives in the contract; the health-score layer supplies only the threshold
values. cross_project_conflicts[] makes the Cross-Project RAID (S6) and Resource Conflicts (S8)
sections render deterministically from fields, not agent-synthesized prose.
Portfolio Health Hard-Gate (Rules 1-3) — the right-sized health-scoring layer. The portfolio
Health summary is governed by a three-rule hard gate applied to the composed output at the
Section-6 human checkpoint (below) — NOT by a parallel numeric scorer. The gate is right-sized
deliberately: it KEEPS the pain-sourced freshness-validation + hard-gate core and TRIMS the
article-sourced elaboration. An A–F letter grade, a multi-layer category-score rubric, and an
integrity multiplier are not introduced — the worst-component dominance rule (Rule 1) already
delivers "cannot show Green over a failing component," so a parallel numeric multiplier would fork
the RAG health SSOT. The WHEN…THEN scoring logic is these three rules; the deterministic
composer's SECTION_REGISTRY renders the sections, so this layer supplies the gate logic + the
section schemas below, never a second renderer.
- Rule 1 — worst-component dominance (live; cite, do not re-derive). A project's
Healthcell is driven by its worst component and CANNOT read 🟢 GREEN while any component RAG is worse than green. This is the existing watermelon-prevention dominance rule — §7.1 W2 plus the Section 7 ↔ Section 1 worst-component feedback below, owned bychannel-formats.md§ RAG Threshold Standards and registered inmetric-registry.md§ Project-Level RAG Composition ("does not define a divergent composition algorithm"). Rule 1 binds that OUTCOME at the summary cell; it authors no new algorithm. - Rule 2 — freshness auto-degrade arm. The per-project
Last-Validatedstamp (thelast_publishedfield consumed above) drives the ONE staleness mechanism owned by the portfolio write-back contract (portfolio-writeback-contract.md§3; age =today − last_published, business days). This layer supplies only the two threshold values that parameterize it — no second freshness field is authored: age> 3 bdrenders[STALE]inline onLast-Validated; age> 5 bdauto-degrades — the field is treated as not-Green and theHealthcell CANNOT read 🟢 GREEN, annotated[STALE:DEGRADED](the composer's degrade marker). Rationale for> 5 bd: a report one full weekly-rollup cycle plus a grace day unrefreshed is no longer trustworthy as green. - Rule 3 — non-override-to-Green. A 🟢 GREEN that contradicts Rule 1 or Rule 2 is REJECTED at
the Section-6 human checkpoint — a silent hand-edit to green is not accepted. To change a derived
color the operator fixes the component SSOT (which re-derives the summary) OR attaches an
evidence-tagged Override Record —
rationale · owner · date— surfaced alongside the write-back proposal, never a silent recolor. This preserves the existing posture that a flag is an evidence-integrity finding, not a unilateral re-coloring. An Override Record is a decision-class action and carries its reversibility tier per § Reversibility Discipline.
What gets written back:
For each active project in PORTFOLIO.md:
Portfolio Health Summary table (S1) — Update the row:
Phase: Current phase from this week's analysisHealth: 🟢/🟡/🔴 as determined in Section 1, subject to the Portfolio Health Hard-Gate above — Rule 1 (worst-component dominance) and Rule 2 (freshness auto-degrade on a[STALE:DEGRADED]Last-Validated) can each block a 🟢 GREEN, and Rule 3 rejects a non-derived green at the checkpoint.Critical Path Item: Top blocker or next milestone from Section 2Go-Live: Updated if date changed during the week (evidence-tagged)Last-Validated: The rollup'slast_published(ISO date) — the per-project freshness stamp that drives the[STALE]/[STALE:DEGRADED]marker (Rule 2). Distinct from the portfolio-levelLast Updatedmeta line (item 4), which stays.
Health Indicators table — Update each dimension:
Schedule: Status + 1-line evidence from this weekScope: Status + 1-line evidenceQuality: Status + 1-line evidenceStakeholders: Status + 1-line evidenceIntegration Risk: Status + 1-line evidence (if applicable)
Top Risks (S5) — Replace with the current top risks (max 5) as passive-voice-free
risk · owner · mitigationtriples sourced from thetop_risks[]contract field (RAID Item —summary+impact→ risk;owner_person_id→ Person → owner;action_plan→ mitigation), rankedseveritydescending thenimpact. Each row names the risk, a named owner, and a named mitigation; a row missing an owner or a mitigation renders[DRIFT: incomplete risk record — <field> missing], never a passive statement (CLAUDE.md § Guardrails, "No passive risk voice"). A cross-project risk is not restated here — it lives in the S6## Cross-Project RAIDroll-up (Section 3.6) and is referenced withsee Cross-Project: [item](dedup — one surface). Renders[STALE]per the contract's freshness marker when the source ages past cadence.Last Updated — Set to today's date
Portfolio-level health-score sections (S3 / S4 / S6 — composed + staged). Beyond the
per-project row above, the health-score layer stages three portfolio-level sections. Each is
rendered by the deterministic composer's SECTION_REGISTRY from the contract fields — this layer
owns the SCHEMA (columns + degrade rules), never a parallel renderer, and stages the result at the
Section-6 checkpoint (never a Claude-side projects/ write):
- S3 —
## Capacity Dashboard(absorbed capacity-view scope). Per-project rowsProject | Utilization | Demand-Supply Gap (RAG) | Over-committed?plus a portfolio roll-up line, readingcapacity_signal {utilization, gap_rag}from the contract. This STAGES the existing §7.5 Capacity Dashboard synthesis — which already appliescapacity-model.md§1 (effective-capacity) and §9 (Demand-Supply-Gap RAG bands:≤ 0.85GREEN …> 1.00RED over-committed) by reference — it does not re-derive the formula or bands. Graceful degrade: a project with no tracked managed-delivery-team allocation renderscapacity: n/a — no managed-team allocation; never fabricate a utilization (the capacity model applies to a managed delivery team, not to the single-operator platform). - S4 —
## Portfolio R-G-T Allocation(absorbed investment-mix scope). Run / Grow / Transform counts (or effort-weighted shares where effort is available) plus an explicitUnclassifiedcoverage-gap line. This STAGES the existing §7.3 R-G-T synthesis, reading each active project's optionalinvestment_class: Run|Grow|Transform. No-invention (already codified §7.3): a project with noinvestment_classisUnclassifiedand surfaced as a coverage gap — never heuristically auto-classified from phase or type. (R-G-T investment classification is not thecapacity-model.md §560/20/20 capacity effort-split.) - S6 —
## Cross-Project RAID(shell + fill). Placed immediately after## Cross-Project Dependencies(both are portfolio-tier cross-project surfaces). Shell columns:Type (R/A/I/D) | Item | Owner | Mitigation | Source-Tier | Projects-Affected. Each populated row is a passive-voice-freerisk · owner · mitigationtriple; Source-Tier enumerates the existing escalation ladder (escalation-thresholds.md§2: Team → Project → Program → Program-Critical/Sponsor → Portfolio). Empty-state:No cross-project RAID items — [N] per-project risks tracked in project details(an honest empty state, not a blank section). The shell — columns, placement, and empty-state — is defined here; its rows are filled by the 3-leg cross-project risk aggregation in Section 3.6 above: Leg 1 aggregates the project-scopedtop_risks[](RAID Item, rankedseveritythenimpact), Leg 2 surfaceskey_dependencies[](Cross-Project Dependency,open/broken), Leg 3 surfacescross_project_conflicts[](Cross-Project Resource Conflict,detected/acknowledged) — each projected into the shell columns as a passive-voice-freerisk · owner · mitigationtriple with itsSource-Tier. Because all three are contract fields, the deterministic composer renders S6 from them (no agent-synthesized rows), staged at the Section-6 human checkpoint (never a Claude-sideprojects/write). S5 (per-project### Top Risks) and S6 (cross-project aggregated) are distinct scopes of ONE risk model — composed, never a parallel section.
Write-back rules:
- Only update fields where the weekly analysis produced new evidence
- Tag every changed field with the evidence source:
[SOURCE: Daily Status 3/17],[SOURCE: RAID R-PPM-052], etc. - If a field hasn't changed this week, leave it as-is (don't rewrite identical content)
- If health color changes (e.g., 🟢 → 🟡), note the reason inline
- Present the proposed PORTFOLIO.md changes as a summary for user approval before writing
- Format: "PORTFOLIO.md Update: [N] fields changed for [Project Name]. [1-line summary of most significant change]."
Human-in-the-loop checkpoint: After producing the executive summary and before writing to PORTFOLIO.md, present:
📊 Portfolio Write-Back Summary:
- [Project 1]: Health 🟡→🟢 (all blockers resolved this week). Phase unchanged.
- [Project 2]: Phase "Testing" → "Issue Resolution". 3 risk updates.
Approve these changes to PORTFOLIO.md? (Or provide corrections)
Wait for user confirmation before writing. If running as a scheduled task, produce the summary and changes as a draft — flag for approval at next interaction.
Section 7: Portfolio Governance
Sections 1–6 surface and write back portfolio state. Section 7 applies portfolio
governance discipline to that state: it catches green-on-the-outside-red-on-the-inside
projects, audits the metric set's balance, reports the investment mix, validates every
reported metric against its governing rule, and synthesizes a portfolio capacity view.
All five sub-blocks consume governed reference docs by role (see ## Reference docs) —
they do not restate thresholds, signals, or formulas.
Run Section 7 over every active project — including a single-project portfolio (the dashboard/cross-project sections are skipped at one project per § Multi-Project Handling, but the per-project watermelon scan and metric validation still run).
7.1 Watermelon Scan (8-signal, per project)
For each active project, run the 8-signal watermelon scan W1–W8 by reference per
watermelon-detection.md
(owned by pmo-qa-auditor — core module, consumed via-public-api; do not restate or fork
the signals). The signals key off the bands owned by metric-registry.md:
| ID | Signal (by reference) | Severity |
|---|---|---|
| W1 | Persistent-green under recurring RAID | STRONG |
| W2 | Green project-RAG over Amber/Red component-RAG | STRONG |
| W3 | Stale / overdue RAID under green (the headline path) | STRONG |
| W4 | Velocity spike beyond credible band | WEAK |
| W5 | Zero open risks on an active project | WEAK |
| W6 | Milestone dates not aging (flat %-complete) | WEAK |
| W7 | 100% task completion under slipping features / scope | WEAK |
| W8 | Self-reported RAG without objective derivation | WEAK |
Apply each signal's false-positive filter (per the canonical doc) before counting it as
fired, then compose the per-project verdict by reference to watermelon-detection.md
§ Verdict Composition:
- ≥1 STRONG signal (W1/W2/W3) fires → WATERMELON-FLAG (Tier 1). Cite the firing STRONG signal + its evidence (e.g., for W3: the overdue RAID IDs + the Overdue-RAID-Count registry band).
- ≥2 independent WEAK signals (W4–W8) fire on the same project → WATERMELON-FLAG (Tier 2). Cite the ≥2 corroborating signals. (W8 corroborates only a non-W8 WEAK; same-evidence items de-dup to their highest-severity facet once.)
- ≥1 signal un-evaluable (missing artifact / metric) and no STRONG independently fired → INDETERMINATE / EVIDENCE-GAP — record the gap; never report this as clean.
- All signals evaluable and none survived → NO-FLAG (CLEAN) — record the signals evaluated and the FP filters that explained near-misses, so a clean result is distinguishable from an un-evaluated one.
Output, per project: the verdict (Tier 1 / Tier 2 / INDETERMINATE / NO-FLAG), the firing signals with evidence, and — for any flag — a one-line statement that the project's Section 1 color is contradicted by the scan. A flag is an evidence-integrity finding, not a unilateral re-coloring: route it to the worst-component dominance check below and the failure-mode rule.
7.2 Lag-to-Lead Balance Audit
Classify each metric in metric-registry.md that the roll-up reports this week as a lagging
or leading indicator (the classification is a property of the registry rows — see the
registry's lag/lead column; no new PROJECT.md field), and report the lag : lead ratio
across the reported set. A set dominated by lagging indicators (outcomes already realized — SPI,
CPI, overdue counts) with few leading indicators (predictive — velocity variance, capacity
utilization, dependency health) is surfaced as a balance risk: the portfolio is being steered
by the rear-view mirror. Cite the registry rows; do not re-derive the metrics.
7.3 Portfolio R-G-T Allocation
Report the portfolio Run / Grow / Transform investment allocation. Read each active project's
optional investment_class: Run|Grow|Transform field from its PROJECT.md (see
project-md-template.md — the field is optional). Compose the portfolio split as the
Run / Grow / Transform counts (or effort-weighted shares where effort is available).
Default when the field is absent: a project with no investment_class is classed
Unclassified and surfaced as an explicit coverage gap — it is never silently
bucketed into Run/Grow/Transform, and it is never heuristically auto-classified from phase
or project-type (that would fabricate an investment call the operator did not make — a
no-invention violation). The R-G-T block therefore works with or without the field: present
field → real split; absent field → Unclassified with the coverage gap named. Do not block the
roll-up on missing investment_class.
Disambiguation: R-G-T (investment classification) is not the
capacity-model.md §560/20/20 capacity effort-split — a different concept that happens to share digits. Do not conflate the two.
7.4 Per-Metric Decision-Rule Validation
For each metric surfaced anywhere in the roll-up (Sections 1–2 health logic, Section 7
sub-blocks), cite its governing WHEN…THEN… decision rule verbatim from its
metric-registry.md row and confirm the reported RAG matches the rule's output. This is pure
consumption: follow REFERENCED rows to their owning doc (channel-formats.md, capacity-model.md,
backlog-health.md) for the live band; do not re-derive a threshold (duplicate-source-
discipline). A reported color that does not match its rule's output is itself a finding (a
likely W2 or W8 watermelon contributor) — surface it, do not silently re-color.
7.5 Capacity Dashboard
Synthesize a cross-project capacity view: aggregate each active project's Capacity
Utilization (the metric-registry.md Team row, which already references
capacity-model.md) into a portfolio
capacity dashboard, applying capacity-model.md §1 (effective-capacity formula) and §9
(Demand-Supply Gap RAG bands) by reference. Report per-project utilization + the portfolio
roll-up, flagging any project breaching the §9 RED band (> 1.00 utilization) as over-committed.
Reproduce the source's inclusivity (≤ 0.85 is GREEN); do not restate the formula or bands.
7.6 Portfolio Dormancy Sweep
For each tracked project, run a dormancy sweep that detects a project producing no artifact activity at all across a defined window and routes it to an explicit disposition decision — distinct from the §7.1 W6 signal and the "Roll-up generated as a substitute for the week's unprocessed work — TRIG" failure mode, which detect stale content within a reported week; §7.6 detects whole-project no-activity and routes to disposition, not a watermelon flag.
- Artifact-activity signal set (per project): the most-recent modification across {Daily
Status Log entries, any
04-PMO-Operations/tracker update, any05-Transcripts/arrival}. "Activity" = a substantive entry/update, mirroring the Stale-RAID "substantive update resets the clock" rule (../ppm-agent/references/escalation-thresholds.md§3) — a cosmetic re-save does not count. - Dormancy clock:
today − last-artifact-activity-date, in business days (carries[INFERRED: today − last-activity-date]per the platform's existing age-computation precedent — there is no codified business-day calendar primitive yet). - Fire condition —
> 10 business days(= 2 weekly-rollup cycles): emit a dormancy prompt for that project naming (a) the project, (b) the last-activity date + its source, (c) the computed dormancy age, and (d) the three disposition options — proceed / shelve / close. The window is 10 business days: it requires a project to miss two consecutive rollup windows (the rollup runs weekly per § Generation Schedule) and reuses the platform's existing 10-business-day "inactivity → disposition" cadence (08-Generated/auto-archive). - Disposition routing (Autonomy Tier 1 — recommend): the prompt is an evidence-integrity finding surfaced to the operator. The sweep never auto-shelves or auto-closes; disposition is an operator decision (mirrors §7.1's "a flag is an evidence-integrity finding, not a unilateral re-coloring"). The dormancy prompt is a decision-class output — carry a reversibility tier per § Reversibility Discipline (an internal pre-confirmation dormancy flag is CHEAP; a close disposition acted on downstream escalates per the tier table).
- Coverage-gap honesty (composes with the "Daily-log coverage gap read as a quiet week —
INPUT" failure mode): if the activity signal cannot be computed (no trackers present yet —
a just-initiated project), emit
dormancy: not assessable — no tracker baselineand flag it as a coverage gap; never read "no trackers" as "dormant" (that would converge with the "absence of evidence becomes evidence of absence" anti-pattern the skill already guards). - De-registration sub-case: a project that is archived but still on the active list fires
the same sweep → the disposition prompt's close option doubles as the de-registration
trigger (drop from PORTFOLIO.md active list). This sweep is the detector;
project-initiatorMode B is the executor (the closure-entry dormancy hook in that skill acts on what this sweep detects).
Section 7 ↔ Section 1 feedback (worst-component dominance). The watermelon scan's W2 signal
(green project-RAG over a worse component) requires the worst-component dominance rule to
detect a violation of. Section 1's project color is therefore composed by the transparent-roll-up
rule — the project color is driven by its worst component (the dominance reading of the
Watermelon detection rule under channel-formats.md § RAG Threshold
Standards, which requires component-level RAGs to
roll up transparently to the project-level RAG; "worst component" is this platform's name for that
r
…(truncated)