| name | oat-project-summary |
| version | 1.2.0 |
| description | Use when the user requests or confirms summarizing an active OAT project — e.g. "summarize the project", "generate the summary", "run oat-project-summary", or confirms a previously offered summary run. Do NOT auto-invoke when implementation completes. Generates summary.md from project artifacts as institutional memory. |
| disable-model-invocation | false |
| user-invocable | true |
| allowed-tools | Read, Write, Bash(git:*), Bash(oat config:*), Bash(oat decision:*), Glob, Grep, AskUserQuestion |
Project Summary
Generate a durable project summary artifact from project lifecycle artifacts.
Purpose
Produce a summary.md that serves as institutional memory — capturing what was built, why decisions were made, what tradeoffs occurred, and what follow-up work was identified. This artifact is distinct from the PR description: summary.md is reflective and thorough; PR descriptions are reviewer-oriented and actionable.
Prerequisites
Required: Active project with implementation.md that has meaningful progress (at least one completed task).
Mode Assertion
OAT MODE: Summary Generation
Purpose: Synthesize a structured summary from project artifacts, grounded in what actually happened.
Progress Indicators (User-Facing)
When executing this skill, provide lightweight progress feedback so the user can tell what's happening after they confirm.
-
Print a phase banner once at start using horizontal separators, e.g.:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
OAT ▸ SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
Before multi-step work, print step indicators, e.g.:
[1/5] Resolving project + reading artifacts…
[2/5] Checking for existing summary…
[3/5] Generating / updating summary sections…
[4/5] Promoting key decisions to reference/decisions/ (if PJM installed)…
[5/5] Committing…
BLOCKED Activities:
- ❌ No implementation work
- ❌ No changing project artifacts (other than summary.md)
- ❌ No creating tasks or modifying plan
- ❌ No hand-authoring decision files or editing
reference/decisions/index.md inside its managed markers
ALLOWED Activities:
- ✅ Reading all project artifacts
- ✅ Creating or updating summary.md
- ✅ Committing summary.md changes
- ✅ Promoting the summary's Key Decisions into canonical
reference/decisions/ records via oat decision new (Step 7), gated on the PJM tool pack being installed
Self-Correction Protocol:
If you catch yourself:
- Writing implementation code → STOP
- Modifying plan.md or implementation.md → STOP
- Adding speculative future work → STOP (summary captures what happened, not what should happen next — except Follow-up Items from deferred work)
Recovery:
- Acknowledge the deviation
- Return to summary generation
- Keep content grounded in artifacts
Process
Step 0: Resolve Active Project
OAT stores active project context in .oat/config.local.json (activeProject, local-only).
PROJECT_PATH=$(oat config get activeProject 2>/dev/null || true)
PROJECTS_ROOT="${OAT_PROJECTS_ROOT:-$(oat config get projects.root 2>/dev/null || echo ".oat/projects/shared")}"
PROJECTS_ROOT="${PROJECTS_ROOT%/}"
If PROJECT_PATH is missing/invalid:
If PROJECT_PATH is valid: derive {project-name} as the directory name (basename of the path).
Step 1: Validate Implementation State
test -f "$PROJECT_PATH/implementation.md"
If missing: Block and tell user: "No implementation.md found. Summary requires at least one completed task."
If exists: Read the file. Check for at least one task with **Status:** completed. If no completed tasks, warn: "No completed tasks found. Summary will be minimal."
Step 2: Read Project Artifacts
Read all available artifacts for synthesis:
"$PROJECT_PATH/discovery.md" — initial request, decisions, constraints
"$PROJECT_PATH/spec.md" — requirements, goals (optional — may not exist in quick mode)
"$PROJECT_PATH/design.md" — architecture, key decisions (optional — may not exist in quick mode)
"$PROJECT_PATH/plan.md" — phases, tasks, reviews, deferred items
"$PROJECT_PATH/implementation.md" — task outcomes, deviations, challenges, review notes
"$PROJECT_PATH/state.md" — associated issues, workflow mode
Priority for content: Implementation.md outcomes take precedence over design.md plans. Summary should reflect what actually happened, not what was planned.
Step 3: Check for Existing Summary
test -f "$PROJECT_PATH/summary.md"
If exists (re-run mode):
-
Read summary.md frontmatter tracking fields:
oat_summary_last_task — last task ID when summary was generated
oat_summary_revision_count — revision phases at generation time
oat_summary_includes_revisions — which p-revN phases are reflected
-
Compare to current state:
current_last_task = highest completed task ID in implementation.md
current_rev_count = count of p-revN phases in plan.md
current_rev_list = list of p-revN phase IDs in plan.md
-
Determine update scope:
- If
oat_summary_last_task == current_last_task AND oat_summary_revision_count == current_rev_count: No changes detected. Skip update. Report: "Summary is current. No updates needed."
- If
current_rev_count > oat_summary_revision_count: New revision phases exist. Update: Revision History, What Was Implemented, Follow-up Items.
- If
current_last_task > oat_summary_last_task: New tasks completed. Update: What Was Implemented, Notable Challenges, Tradeoffs Made.
If does not exist (first run):
Copy template: .oat/templates/summary.md → "$PROJECT_PATH/summary.md"
Step 4: Generate / Update Summary Sections
For each section, synthesize content from the relevant artifacts. Apply these rules:
Grounding rule: Prefer implementation.md outcomes over design.md plans. If the implementation diverged from the design, reflect what actually happened.
Design delta rule: Populate Design Deltas from both direct implementation deviations and review-received design drift decisions recorded in implementation.md. A review finding may decide that shipped implementation is defensible and the artifact is stale; when implementation.md records that acceptance, carry it forward as a design delta with the rationale and follow-up artifact disposition.
Section omission rule: If a section would have no meaningful content, omit it entirely (remove the heading). Do not leave empty sections or "N/A" placeholders.
Conciseness constraint (NFR3): Target under 200 lines total. If a draft exceeds this, trim narrative sections (What Was Implemented, Notable Challenges) to essential points. Revision History entries: 2-3 sentences per round max.
Minimum viable summary: Overview + What Was Implemented + Key Decisions. All other sections are included only when they have content worth preserving.
Section sources:
| Section | Primary Sources |
|---|
| Overview | discovery.md initial request, spec.md problem statement |
| What Was Implemented | implementation.md task outcomes, plan.md phase structure |
| Key Decisions | design.md decisions, implementation.md notes/decisions |
| Design Deltas | implementation.md deviations table; review-received design drift notes |
| Notable Challenges | implementation.md issues/blockers in task notes |
| Tradeoffs Made | implementation.md decisions, design.md tradeoff sections |
| Integration Notes | implementation.md notes about cross-cutting concerns |
| Revision History | plan.md p-revN phases, implementation.md revision notes |
| Follow-up Items | implementation.md deferred findings, plan.md deferred items |
| Associated Issues | state.md associated_issues field |
For incremental updates (re-run):
Only update sections affected by the new content. Do not rewrite the entire summary. Preserve existing section content and append/modify as needed.
Step 5: Update Summary Frontmatter
After generating/updating sections:
---
oat_status: complete
oat_ready_for: null
oat_blockers: []
oat_last_updated: { today }
oat_generated: true
oat_summary_last_task: { highest completed task ID }
oat_summary_revision_count: { count of p-revN phases }
oat_summary_includes_revisions: [{ list of p-revN IDs reflected }]
---
Step 6: Promote Key Decisions to Canonical Decision Records
Run this step after summary.md (including its ## Key Decisions section) has been written/refreshed and its frontmatter updated. It promotes the project's Key Decisions out of per-project prose and into the canonical, repo-wide reference/decisions/ log so they stop being siloed in summary.md. This step is additive and non-interactive — it never prompts.
6.1 — PJM gate (auto, no prompt). Check whether the PJM tool pack is installed:
PJM_ENABLED=$(oat config get tools.project-management 2>/dev/null || echo "")
- If
PJM_ENABLED is true → perform the promotion automatically. Do NOT ask the user.
- Otherwise (any other value, empty, or unset) → skip this entire step silently. Do not print a warning or prompt.
6.2 — Skip if nothing to promote. If summary.md has no ## Key Decisions section, or that section has no decision content, skip the step. There is nothing to promote.
6.3 — Ensure the decisions surface exists. The canonical decisions root is .oat/repo/reference/decisions (the oat decision default; pass --decisions-root <path> only for an explicit override). If its managed index is missing — i.e. .oat/repo/reference/decisions/index.md does not exist — initialize it first so oat decision new can succeed:
test -f .oat/repo/reference/decisions/index.md || oat decision init
oat decision init is idempotent; running it when the scaffold already exists is harmless.
6.4 — Idempotent, date-independent promotion (critical). For each decision in ## Key Decisions:
-
Derive title + rationale. The decision's bold lead-in / first clause becomes the title (a short noun phrase). The remaining explanatory text becomes the rationale, passed verbatim as --context.
-
Compute the slug the CLI would use. The CLI generates the record ID as DR-<YYMMDD>-<slug>, where <slug> is the lowercased, ASCII-folded, hyphen-collapsed form of the title, capped at 30 characters at the last whole-word boundary with trailing stop-words (a, an, the, of, for, and, to, in, on, as, with) trimmed (the same slug rule the CLI applies). Compute that <slug> for the title.
-
Dedup on the exact slug, ignoring only the date prefix. A record ID is DR-<YYMMDD>-<slug>, where the date is exactly six digits. Check whether a record for this slug already exists by stripping that fixed DR-<6 digits>- prefix from existing record IDs and comparing the remaining slug for exact equality. Anchor the date to exactly six characters so the slug must match in full:
ls .oat/repo/reference/decisions/DR-??????-"<slug>".md 2>/dev/null
Do not use a loose DR-*-<slug>.md glob: the greedy * would let a short slug (e.g. layers) falsely match a longer record (DR-260623-two-layers.md) and wrongly skip it. (Equivalently, scan the ID column of reference/decisions/index.md, strip each DR-<6 digits>- prefix, and compare the slug exactly.) This date-independent, exact-slug match is essential: the DR-YYMMDD- date prefix changes across re-runs, so a naive full-ID DR-YYMMDD-<slug> check would never dedup, while a loose suffix match would over-dedup.
-
Skip or create.
-
If a matching record already exists (same slug) → skip it. It was already promoted on a prior run.
-
Otherwise → create it:
oat decision new "<title>" --status accepted --context "<rationale>"
The command generates the deterministic DR-YYMMDD-slug ID, seeds the body from .oat/templates/decision.md, and regenerates the managed index automatically — do not hand-edit index.md. Optionally pass --created-at "<project completion date>" when a project completion date is available, so the record's date reflects when the decision was made.
Because of the date-independent slug dedup, this step is safe to run every time summary.md is (re)generated — including the pr-final refresh and revision re-runs — without ever creating duplicate decision records. Already-promoted decisions are skipped; only genuinely new Key Decisions become new records.
Status value: use --status accepted. The decision template's status field (.oat/templates/decision.md) is free-form, and the canonical accepted/decided value in the decision vocabulary (proposed → accepted → superseded) is accepted. A Key Decision in a completed project's summary represents a decision that was made and shipped, so accepted is the correct status.
6.5 — Report, don't prompt. After processing all Key Decisions, print a short informational summary, e.g.:
Promoted N key decision(s) to reference/decisions/:
- created: DR-YYMMDD-<slug> ("<title>")
- skipped (already promoted): <slug>
This is informational only. There is no interactive prompt anywhere in this step.
Step 7: Commit
git add "$PROJECT_PATH/summary.md"
git commit -m "docs: generate summary for {project-name}"
If decision records were promoted in Step 6, also stage .oat/repo/reference/decisions/ so the new DR-*.md records and the regenerated index.md land with the summary.
If this is a re-run (incremental update):
git commit -m "docs: update summary for {project-name}"
Step 8: Output Summary
Summary generated for {project-name}.
Sections: {list of non-empty sections included}
Lines: {line count}
Mode: {fresh | incremental update}
Decisions promoted: {N created, M skipped as already promoted | skipped (PJM not installed)}
Summary tracks: last task {task_id}, {N} revision phases
Success Criteria
- Summary.md exists in the project directory with valid frontmatter
- Content is grounded in implementation outcomes, not plans
- Sections with no content are omitted
- Frontmatter tracking fields are current
- Summary is under 200 lines for typical projects
- Re-run after revisions updates only affected sections
- Re-run with no changes produces no modifications
- When the PJM tool pack is installed, each Key Decision is promoted to a canonical
reference/decisions/DR-YYMMDD-slug record via oat decision new (status accepted), deduped on the date-independent slug so re-runs never create duplicate records
- When the PJM tool pack is not installed, decision promotion is skipped silently with no prompt