Skip to content
Back to skills

Bragdoc

ASecurity

In-depth, metric-backed brag document of the user's engineering and career work (a performance-review and career record). Commands - dump, stage, probe, renovate, brag, extractor. Use whenever the user mentions achievements, brain dumps, work they did, weekly wins, updating their brag doc, an extensive resume, or summaries from coding sessions - even without saying "bragdoc".

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
ai-agentspythonrustgogitapidatabasebackenddevopssecurityperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add aalishan001/opencockpit --skill bragdoc --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Bragdoc?

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

Security grade badge for Bragdoc
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/aalishan001-bragdoc/badge)](https://www.skillsdirectory.com/skills/aalishan001-bragdoc)

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: bragdoc
description: In-depth, metric-backed brag document of the user's engineering and career work (a performance-review and career record). Commands - dump, stage, probe, renovate, brag, extractor. Use whenever the user mentions achievements, brain dumps, work they did, weekly wins, updating their brag doc, an extensive resume, or summaries from coding sessions - even without saying "bragdoc".
---

# bragDoc

**No command given** (bare `/bragdoc`): read `COMMANDS.md` and print its `## bragDoc` section verbatim (heading through the line before the next `## `) in a fenced code block. Nothing else, no commit.

"An in-depth, detailed brag document of all my engineering and career work."

Pipeline: `dump → staging (raw) → probe → staging (probed) → renovate → entries.jsonl → rendered PDF`

- `data/bragdoc/entries.jsonl` is the source of truth. The PDF is always rendered from it by script, never hand-written.
- Facts in an entry change only through **probe** or my explicit correction, and always shown as a diff.
- Every staging item and every probe transcript is kept: `data/bragdoc/probes/<staging-id>.md`.

## Impressiveness scoring (`rank_score` 1–10)
Measured relative to an engineer in the same field with my tenure (`career_start` in `data/profile.json` → today). Ask: "For someone this far into their career, how cool is this?"
- 9–10: rare at this tenure (owned a system end to end at scale, a significant measurable business or perf impact, novel design)
- 7–8: clearly above peers (led a feature across services, strong metrics)
- 5–6: solid, expected of a good engineer at this level
- 1–4: routine; keep it for completeness
Always write a one-line `rank_rationale`. My override wins; record it as `rationale: "user override: ..."`.

## Commands

### dump (one-off; show a plan with counts and wait for my go before writing data/)
Accept text, files, or folders (brain dumps, old resumes, docs). Move originals to `raw/bragdoc/<YYYYMMDD-HHMM>-<name>` (images via `python scripts/ingest_images.py bragdoc <paths>`). Never edit originals. Single items (and other domains' handoffs) are appended with `python scripts/bragdoc_stage.py add -`.

**Source trust tiers.** Tag every extracted claim with its source file and tier, stored per item as `source_claims: [{claim, value, source, tier}]`:
- **T0**: my explicit statements in chat (`source: "user"`). Always wins.
- **T1**: my own notes (newest first).
- **T2**: resumes I approved (newest first; older versions mostly superseded). Claims that appear only in resumes are true and defensible; stage them for depth, never mark them unverified.
- **T3**: AI-generated text (summaries, other assistants' dumps). Anything only in T3, or marked "assumed", "inferred" or "WEAK", gets `needs_confirmation: true` and must be confirmed in probe before it reaches an entry.
- From T3, extract only facts (numbers, names, events, technologies, outcomes), not reworded purpose statements. A T3 claim restating a T0–T2 fact joins that claim's group, so it isn't flagged.
- When T0 overrides a lower-tier value, keep the old record with `superseded: "<why>"`.

**Deduplication.** One staging item per distinct achievement; merge every mention across files, keeping all variants in `source_claims`. Dedupe against existing `staging.jsonl` and `entries.jsonl` too.

**Batches.** One project per batch: `b-<date>-<project-slug>`. Large projects split by sub-area (e.g. a platform split into access control, report pipeline, ingestion, …). Each item also carries `project` and `employer`.

**Conflicts.** When non-T0 sources disagree, add `conflicts: [{field, values: [{value, source, tier}], status, ...}]`. Open conflicts get a question in `questions.jsonl` (`topic: "conflict"`) citing each value and its source; T0- or script-settled ones are `status: "resolved"` with a `resolution`. Never ask about anything a script can compute (ratios, percentages): run the script and store the result.

**Pre-probed fast path.** Fill `probe` fields from sources for every item (only T0–T2 facts, never T3-only ones). An item goes straight to `status: "probed"` only if it meets the completeness criterion below *and* has no open conflicts, no `needs_confirmation` claims and a known `kind`. Otherwise `status: "raw"` with `open_gaps` listing exactly what's missing, so probe asks only that. For each fast-path item, write `probes/<id>.md` listing the claims each field came from, and add a confidentiality question (`topic: "confidentiality"`): "anything here not OK to say publicly?" (the fast path skips the probe's own question).

**Everything goes in the bragDoc.** Achievements, including community, teaching, leadership and competitions, go through staging (non-engineering ones: `kind: "community"`, category "Community & Leadership" at renovate). Other material goes to its own file (schemas in `scripts/schemas.md`):
- skills → `skills.json` (level only in my own words; evidence via `evidence_staging_ids` until renovate)
- education → `education.json`
- employment history → `employment.json` (employer, role, start, end, source; company awards and team size as `context`, never as my achievement; no salaries, addresses or phone numbers). `context` is internal: only the internal bragDoc shows it. Every resume and the public PDF use the user-approved `public_summary` (one sentence under the role) and `public_context` (lines) instead
- unfinished work → `in_progress.jsonl` (promote to a staging item when completed)

After writing: a table per batch (items, probed/raw, open gaps, conflicts), then all questions grouped by batch with conflicts first. Validate, commit, push.

### stage (one-off)
Table of staging items: id, batch, one-line summary, status, open gaps. Group by batch. Exclude `merged` unless asked.

### probe (back and forth; ends on `/end` or auto when the item has no open gaps)
Take one raw item or batch (I can name one; default is the oldest raw batch).

Before asking anything: read the item's `open_gaps`, `conflicts` and `source_claims`, then look up its project in `data/bragdoc/probe_bank.md` (if present). Skip every bank question the item's data already answers. Order: open conflicts (with their questions in `questions.jsonl`), then `needs_confirmation` claims, then the other gaps, then bank questions. When I answer a conflict or confirm a claim, record my answer as a T0 claim, resolve the conflict or clear the flag, and mark the question answered.

Grill like a senior engineer reviewing me for the next level:
- **Problem:** what was broken or missing, and who felt it
- **Action:** what *I* did versus the team, and the decisions and trade-offs I made
- **Result:** before/after metrics (latency, users, time saved, error rate, revenue), and how I know
- **Scope:** systems, scale, and stakeholders touched
- **Stack:** specific technologies
- **Logic gaps:** call out inconsistencies, vague verbs ("helped", "worked on"), and unverifiable claims

Near the end of each item, ask naturally as part of the conversation (not as a form):
- **Kind:** is this work for an employer/client, a personal project, a product (has users / a landing page), an open-source contribution, or community (teaching, volunteering, competitions, clubs)?
- **Links** (non-work only): repo, live URL, landing page, demo, docs.
- **Confidentiality:** "Is anything here not OK to say publicly: client names, internal numbers, system names, unreleased features?"

One question at a time. Estimated metrics are allowed only if labelled as estimates with the method stated.

**Completeness criterion ("probed")**, enforced by `validate.py`:
- `problem`, `action`, `result`, `my_role` and `stack` filled
- at least one **scale** metric (users, records, requests/day, team size) and one **impact** metric (% improvement, time saved, issues resolved), each tagged `type: "scale" | "impact"` in `probe.metrics`
- an **ownership** signal in `my_role`/`action` (led, designed, owned, independently built)
- **no passive verbs** (worked on, helped, assisted, was responsible for)
- no open conflicts, no `needs_confirmation` claims, empty `open_gaps`
- **Answered without data** (my AS-IS, or "don't know" to a metric or the stack): `probe.waived` = `{fields: [scale|impact|stack|problem], source: "user, <date> (<answers file>)", reason}` exempts exactly those parts, nothing else. Only my answer waives; never fill the gap with an estimate instead

Save the transcript (these answers included, like every other answer), fill `probe` including `kind`, `links`, and `public_constraints` (if I say "nothing", store `[]` explicitly), set `status: probed` (or `probing` if ended early, with `open_gaps` listed). Commit.

### renovate (one-off)
1. For each `probed` item, create or merge into an entry: professional resume-style phrasing, all details kept, no redundancy. Set `status: merged`.
   - Carry over `kind`, `links`, `public_constraints` from the probe (merging items: union of constraints, merge links). Create every new entry with `python scripts/bragdoc_public.py add-entry '<json>'`: it assigns the id, `published_hash: null` and the **standing visibility default** (`data/runway/config.json` → `visibility_default`, the user's own rule; the template ships with every new entry private): for example public, unless the entry is the current employer's (then private). Never set `visibility` by hand; later changes only via set-visibility on the user's word. A merge into an existing entry never changes its visibility, `site_slug` or `published_hash`.
   - Kind unknown: `work` if `employer` is set; otherwise add a `topic: "kind"` question to `questions.jsonl` and leave the item in staging until answered.
   - Carry the staging item's `employer` into the entry. Then swap staging ids for entry ids in `skills.json` (`evidence_staging_ids` → `evidence_entry_ids`) and in `education.json` (`capstone.entry_id`).
2. Recategorize all entries into loose technical categories (e.g. Backend & APIs, Data & Databases, Cloud & DevOps, Mobile, Performance, Architecture). No timeline narrative. `kind: "community"` entries (teaching, volunteering, competitions, clubs, podcast) go in "Community & Leadership", ranked within it like any category.
3. Re-rank within each category by `rank_score`, highest first.
4. Show the diff summary (new, merged, re-ranked, recategorized). Write, validate.
5. **Public layer: everything the site needs, for EVERY entry whatever its visibility** (nothing is generated at publish time):
   - `python scripts/bragdoc_public.py stale` → for each listed entry and channel, write the text under that channel's rules (below) and save it: summaries with `python scripts/bragdoc_public.py set-summary <id> '<json>' --channel public|resume`, site cards with `python scripts/bragdoc_public.py set-card <id> '<json>'` (`{metric, context, did, result, where}` with a short metric, public rules, the entry's own employer deciding which figures it may carry). The scripts stamp `generated` and `source_hash` and reject anything `disclosure_lint` blocks; fix and resave. No approval step.
   - `python scripts/bragdoc_public.py finalize`: sets `year` on entries and staging items (period, else `data/bragdoc/project_years.json`, else a single-year tenure), cuts each missing `site_slug` from the public headline (never changed afterwards), and lists anything still missing; repeat until it reports every entry complete. An entry with no year rule: ask for its year and add it to `project_years.json`.
   - `python scripts/bragdoc_public.py missing-links --add-questions`
   - `python scripts/bragdoc_public.py pending`
6. Run `python scripts/render.py bragdoc`, which produces `out/<names.short>_BragDoc.pdf` (HTML fallback if PDF tooling is missing): Experience (from `employment.json`), the ranked categories, Skills, Education, Community & Leadership, In Progress. Show the path.
7. Commit and push. End the output with:
   ```
   Public layer
   - N summaries generated/refreshed
   - N public entries pending a site update: <titles>
   - N non-work entries missing links
   ```
   Then, automatically: `python scripts/runway.py publish --if-pending`. When any public payload changed, it ships to the site repo's `content` branch and prints the preview URL (add it to the output); otherwise it does nothing. It never touches `main`: promote stays manual (`/runway promote`), the one human gate before anything goes live.
   Then: `python scripts/profiles.py policy`, and add its reminder (if any) to the output: which profile pieces are stale and why (EXTROVERT `profiles`).
   Then: `python scripts/repos.py status`, and add its reminder (if any): which public repos need fresh metadata suggestions (EXTROVERT `repos`).

Items not yet probed stay in staging.

## Disclosure channels
Everything that leaves the bragDoc goes through one of three channels defined in `data/bragdoc/disclosure_policy.json` and enforced by `python scripts/disclosure_lint.py --channel internal|resume|public <file>`. Renders lint themselves and write nothing on failure; a failure shows the offending lines, which get fixed (usually by regenerating that entry's channel summary). Nothing ships with a lint failure.
- **internal** (`render.py bragdoc`): only me. Full entry detail, security specifics, all contacts, cost figures.
- **resume** (`render.py resume-extensive` and any resume built from the bragDoc): written from `resume_summary` + resume contacts (phone and the personal email; resumes always use the personal email, never the domain email).
- **public** (the website, shipped by RUNWAY; `render.py public-resume` is its PDF, served as `/<names.short>_Resume.pdf`, public entries only): written from `public_summary` and `site_card` + public contacts (the domain email, never phone or personal email).
- **Names** (`data/profile.json` → `names`; each channel's form is in the policy): internal renders show `short`, resume renders `formal` exactly as stored, the public resume `public_full`. Summaries and other public prose use `short`, or `public_full` only where a full name is genuinely required. Never type a name into an output; an all-caps design is CSS `text-transform: uppercase`, never changed text. The lint flags any wrong casing of the formal name on every channel.

## Public layer
Cockpit prepares public data; only RUNWAY ships it (`/runway`). `published_hash` is set only by `runway.py promote`, never by hand or by bragdoc.

Two channel summaries plus one site card per entry (cards follow the public rules below). Summaries share one structure (`headline` ≤ 12 words, `summary` 2–4 sentences, `highlights` 2–4 short bullets, `stack` public tech only) and the same `source_hash`/stale machinery. Both are generated for **every** entry regardless of visibility, from the entry, its probe transcript, `public_constraints`, and common sense.

**Resume summary** (`resume_summary`; anyone reading your resume sees it):
- Remove: internal system/service/table names, proprietary platform internals, exploitable security specifics, anything in `public_constraints` (e.g. no security details tied to a named client).
- Allowed: client/employer names, project/app names, generic vulnerability classes (the categories listed in the policy), engineering metrics (latency, throughput, test counts, coverage like 66/66), business scale (users, records).
- Employer money figures: relative change only, never absolute values.

**Public summary** (`public_summary`) redaction rules, always applied, even when `public_constraints` is empty:
- Everything the resume summary removes, plus: no vulnerability class names (keep the achievement: "hardened external document fetching", not the class name).
- Costs (the user's rule): relative cost changes (a percentage cut in hosting spend, say) from past employers', clients' or personal work are allowed; absolute amounts (currency amounts, per-month figures) never; any cost figure about the current employer never. The current employer is always the open role in `employment.json`, so a job change re-tiers this automatically.
- Never include anything in `public_constraints`.
- Client/employer and project/app names are allowed, but never alongside security details for that client. Work entries: no internal system/service names; no security architecture details or vulnerabilities; no unreleased features or roadmap.
- Business numbers (the user's rule, enforced by disclosure_lint): user counts and usage scale (users, downloads, concurrent users, records, sites) from past employers', clients' or personal work are allowed; the current employer's user, tenant and customer counts never; revenue and contract values never, for any employer. Per-entry `public_constraints` still win.
- Allowed: employer name, the problem type in generic terms, my role, public technologies, and impact as relative change ("cut p95 latency by ~60%") when the absolute numbers aren't sensitive (money figures: see above). Compute the change with `python scripts/bragdoc_public.py change <before> <after>`, never in your head.
- Personal projects, products, open source, community: anything I'd put in a public README is fine; still respect `public_constraints`. Only personal projects, products and open source are expected to have links.
- Never add claims not in the entry. Same truthfulness rules as the rest of bragDoc.
- Tone: confident, concrete, no buzzwords; readable by any engineer or reviewer.

**Visibility:** changes only when I explicitly say so. "make <entry> public|private" (by id or title; if ambiguous, ask which) → `python scripts/bragdoc_public.py set-visibility <id> public|private`, show the entry's `public_summary`, commit, push.

### brag (one-off)
Run `python scripts/render.py resume-extensive`, which produces `out/<names.formal>_Resume_Extensive.pdf` (spaces as underscores) on the **resume channel**: ATS-friendly, single column, standard headings, the whole bragDoc except In Progress, written from each entry's `resume_summary` with resume contacts. The render lints itself; on failure, show the offending lines, fix the summaries, re-render. Show the path.

### extractor (two steps: emit a prompt, then take the summary back as a dump)
Modes, one prompt per kind of source:

| Command | Prompt for |
|---|---|
| `/bragdoc extractor` | **session** (default): the work done in the current AI pair session / repo |
| `/bragdoc extractor incident <date> <short description>` | one incident: timeline with timestamps (first symptom, detection, diagnosis, mitigation, resolution), durations computed from the timestamps, impact, root cause, fix, prevention added, what I'd do differently |
| `/bragdoc extractor project` | one project: what it is, owner (personal / employer / client), status and dates from git, architecture and data flow, decisions and trade-offs, evaluation, metrics, what's novel, stack, links |
| `/bragdoc extractor period <from> <to> <topic>` | multi-month work (e.g. a quarter-long migration or a pipeline rebuilt over several iterations): phases, the problem before, what changed and why per phase, metrics then vs now (still true?), ownership, decisions, what went wrong and the fix, stack |

1. **Emit (one-off, writes nothing, no commit):** `python scripts/extractor.py prompt <mode> [args] [--personal]`, shown verbatim in one fenced block, ready to paste. The script writes every prompt; never hand-write, trim or reword it. Every prompt carries: a READ-ONLY block (no file edits, no commits/pushes/branches/stashes, no migrations, builds, tests, scripts or DB queries; read files and read-only git only; answer in chat, save nothing), evidence tags on every number and claim (`[measured]`, `[from git/logs/docs]`, `[estimate]`, `[from my memory]`), strict ownership (mine vs others'), a confidentiality block, and a closing "Notes for you" (what was left out and why, what's unverified). The confidentiality block (no code, hostnames/IPs/URLs, credentials or env values, table/service names, client names, exploitable specifics) stays unless the work clearly belongs to no employer or client; only then pass `--personal`. If unsure, keep it. Incident dates and period bounds are checked by the script.
2. **Paste-back** (when I paste the summary): it is a **dump**, so every dump rule applies (tiers, dedupe, conflicts, show the plan and wait for my go), plus:
   - **Source:** `python scripts/extractor.py source <mode>` → `extractor:<mode>:<date>` on every item.
   - **Evidence:** each claim keeps its tag in `source_claims[].evidence` (`measured` | `git` | `estimate` | `memory`). The summary is AI-written, so claims are T3 with `needs_confirmation` as usual; in probe, confirm the `measured` and `git` ones in one batch question. An untagged number is not stored; it becomes a question.
   - **Overlaps first, before creating anything:** for each item, `python scripts/extractor.py overlaps '<json>'` (raw, project, employer, and the incident date or period bounds). Show every likely/possible overlap and ask: merge into the existing item (new claims added to it) or create a new one. Example: an incident write-up vs an existing entry that already mentions the same failed migration that month.
   - **Incidents:** recompute time to detect / mitigate / resolve with `python scripts/extractor.py durations <first_symptom> <detected|unknown> <resolved> [--mitigated <ts>]` (pass `unknown` when there's no detection timestamp; the script then reports only the intervals the timestamps support). If the summary's numbers differ, the script's win and the mismatch becomes a question. Store the timestamps and durations as claims; never "record time" or similar.
   - **Create** with `python scripts/bragdoc_stage.py add -` (status raw; the summary's gaps and its "Notes for you" unverified claims go into `open_gaps`; what it left out for confidentiality stays out). A project whose status is in progress also gets `python scripts/bragdoc_stage.py add-in-progress -` (`kind: project`, `staging_id` = the new item).
   - Validate, commit `bragdoc: extractor: <mode>: <n> items`, push. Offer to probe them.

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.