UNRELEASED DEVELOPMENT SNAPSHOT · READ-ONLY EXCERPT
skills/capture/SKILL.md
This is the cited technical source at local revision 275a354, inspected on 22 September 2026. It differs from the public release. This reference publishes only the cited sections, not an installable release or the development branch.
Line numbers refer to the complete recorded file. Uncited lines are omitted. Full-file SHA-256: d9aa821fd62ecebc46933c3111ae4f58556d78e4b5686ae1a044faa551d858f5.
1
---2
name: capture3
layer: foundation4
description: Use after SHIP, at the end of a task, to make what was learned durable — updates lessons, drafts an ADR for any non-trivial decision, appends the evolution log, and reaffirms the cold-executor handoff trio against build evidence. The cycle's last step; carries continuity to the next session.5
color: cyan6
tools: Read, Write, Edit, Bash, Grep, Glob7
voice: internal8
cli_support: [claude-code, codex, copilot]9
necessity: STRONGLY_RECOMMENDED10
gap_if_skipped: "Lessons, ADRs, and EVOLUTION-LOG entries are never written and the cold-executor trio is never reaffirmed against build evidence; cross-session continuity is lost and the next operator re-derives everything."11
---13
You are the CAPTURE skill — Phase 8 (final) of the Lintel cycle.15
## What this skill does… omitted uncited lines …
89
### Step 2 — Lessons capture (filtered)91
Invoke `/li:learn` (or inline):93
For each correction operator made during the cycle:94
- Was this correction GENERAL (would apply to future work) or SPECIFIC (one-time)?95
- If GENERAL: candidate for `.claude/memory/lessons.md`96
- If SPECIFIC: keep in this cycle's notes only98
Examples of LESSON-worthy:99
- "Don't mock the vendor SDK in tests — last 3 cycles' tests passed but prod failed because mocks diverged from real API"100
- "Always map the codebase first when planning infra work — saved 90 min on this engagement"102
Examples NOT lesson-worthy:103
- "Use specific port 8443 in this customer's deployment" — too specific104
- "Forgot to update README" — operational, not a pattern106
**Update-phase (ADR-0006) — classify BEFORE appending.** Append-only capture is the documented107
failure mode of file-based memory. For each candidate, grep what already exists:109
```bash110
source "${LINTEL_SOURCE_ROOT:-$LINTEL_REPO_ROOT}/lib/memory.sh"111
lessons_find_related <candidate keywords> # all related active lessons, ranked112
```114
Classify against the hits:115
- **add** — nothing related exists → new `## L-NNN — <title>` entry116
- **update** — an existing lesson covers it but the candidate sharpens it → extend THAT lesson's117
How-to-apply (note the cycle id), no new entry118
- **supersede** — the candidate CONTRADICTS an existing lesson → write the new entry, then add119
`superseded_by: L-<new> (<date>)` as the first body line of the old one. Never delete or edit120
the old lesson away — git holds ingestion history, the marker holds validity121
(supersede-don't-delete).122
- **no-op** — an existing lesson already says this → skip, mention the existing id124
AskUserQuestion per candidate lesson: "Capture as <classification>? (yes / no / edit-first)"126
If add: append to `.claude/memory/lessons.md`:127
```markdown128
## L-NNN — <lesson title>129
<lesson body: Rule / Why / How to apply>130
<-- Captured from cycle <cycle-id> by <operator>. -->131
```133
### Step 3 — Promote lesson check (NEW)135
For each NEW lesson captured, AskUserQuestion: "Promote to Lintel global lessons (scaffolding/01-foundation/.claude/memory/lessons.md)? — applies to ALL future scaffolded repos."137
If yes: invoke `/li:lessons-promote`.139
This is how operator-discovered patterns become team-wide knowledge.141
### Step 4 — ADR draft (if non-trivial decision)143
Scan cycle history for non-trivial decisions:144
- Architectural picks (alternative A vs B chosen)145
- Pattern adoptions (new pattern introduced)146
- Trade-off decisions (accepted P3 finding, deferred P2)147
- Scope changes (descoped feature, added scope)149
For each candidate, AskUserQuestion: "Draft ADR for this decision?"151
If yes: invoke `/li:adr-new "<decision title>"`:152
- Reads `.claude/decisions/TEMPLATE.md`… omitted uncited lines …
185
- Update interfaces/contracts that drifted during BUILD (annotated as post-build-evidence)186
- Status: APPROVED (from PLAN) — unchanged unless drift detected188
**`plan.md` reaffirm** (born in PLAN):189
- Annotate plan.md tasks with actual STATUS (DONE/SKIPPED/DEFERRED) from build-log190
- Acceptance criteria post-verification (which actually passed)192
**`prompt.md` reaffirm** (born in PLAN, v3.8 Feature 2.2 moved birth to PLAN):193
- Verify prompt.md still describes the work accurately194
- Add any "What you DON'T need to know" entries discovered during BUILD195
- Path: `.claude/plans/<slug>/prompt.md` (born by PLAN, lives there)197
**Why moved to PLAN:** standalone `/li:plan <design.md>` (workflow_root post-v3.8) needs to produce the complete trio at PLAN-time. CAPTURE-only generation broke that — operator running PLAN solo got 2/3 of a handoff. Trio born together fixes this.199
AskUserQuestion: "Want to dogfood the trio? Spawn fresh subagent with ONLY these 3 files + verify it can describe what was built." (Optional verification step — same as before, but now against finalized trio.)201
**Handoff-size check against the 500k cap (NON-BLOCKING).** The reaffirmed trio is the durable cold-executor handoff — the artifact a fresh cold session reads to re-execute. Run the existing cap check so the finalized trio (now annotated with build evidence, possibly larger than at PLAN-time) plus any warming context can't silently exceed the 500k cap. This closes the second un-gated handoff the v4.9 audit flagged (Promise 6: cap logic existed but was invoked at no handoff).203
Invoke the existing mechanism — do **not** rebuild it:205
`/li:handoff-size-check` (a portable skill call; reads the reaffirmed trio + `.claude/runtime/state/warming-manifest.md`, applies the mode-aware cap from `/li:context-budget` mode_envelopes, default `customer-engagement: 500k soft / 750k hard`).207
- **SURFACE, don't block.** A yellow/red verdict warns ("finalized trio yields ~Nk handoff, near cap") and notes the durable handoff is large — the operator decides whether to trim before it becomes the cross-session record. It does NOT halt CAPTURE.208
- **Off-switch:** `--skip-handoff-size-check` (or `SKIP_HANDOFF_SIZE_CHECK=1`) skips the gate entirely. Silent when skipped, and silent on a green pass.210
### Step 6a — Reaffirm swarm evidence and future-operator clarity212
When the selected work map opts into swarming, resolve helpers only from explicit213
`LINTEL_SOURCE_ROOT`, then Claude's `CLAUDE_PLUGIN_ROOT`; other adapters export their known installed214
bundle. Without either trusted root return `NEEDS_CONTEXT`. Run `li-work-artifacts.py` and215
`li-swarm.py verify` with the working repo only as `--repo`. Tests/self-checks export216
`LINTEL_SOURCE_ROOT` explicitly. Preserve the work map, charter, briefs, worker reports, and217
independent reviews with the trio; they are the cold-resume evidence for topology and ownership.218
Do not copy task text, dependencies, status, or acceptance into coordination.220
Only the coordinator may set the work-map status to `COMPLETE`, and only after all lane evidence,221
serial integration, final integrated REVIEW, and SHIP evidence pass. Local runtime attempt files and222
abandoned worktrees are not durable completion evidence.224
For meta-infra M4, the future-operator recap must name:226
- the explicit opt-in fields and coordination path;227
- the actual host tier used (`native`, `sequenced`, or `none`) and whether writers really ran228
concurrently;229
- the isolation/attribution method and deterministic integration order;230
- lane reports/reviews plus final integrated review evidence;231
- any lost attempts, sequenced fallback, migration, deprecation, or unverified host behavior.233
Never claim independent review when the same identity implemented and reviewed a lane. Honest234
degradation is part of the durable outcome, not a concern to hide.236
### Step 7 — Role debrief (if role was active)238
If role was active during cycle:239
- Review role's OUTCOME LENS per phase against actual outcomes240
- Did role lens add value? Where did it conflict with engineering reality?241
- Update role file with any new INSIGHTS learned (operator confirms)242
- Sensitivity-aware: if role is private, updates stay in `~/.lintel/roles/private/<role-id>.md`244
### Step 7b — Vault sink (session summary → knowledge vault)246
Config-gated, optional, NEVER blocking. Writes a short human-readable session summary to an247
external knowledge vault (e.g. an Obsidian vault) so the vault becomes the cross-repo memory248
layer. The repo's own capture artifacts (Steps 1–7) are unaffected — this is an additional249
sink, not a move. Nothing is ever read back from the vault into the repo.251
```bash252
source "${LINTEL_SOURCE_ROOT:-$LINTEL_REPO_ROOT}/lib/pack-resolver.sh"253
sink_enabled=$(resolve_pack_field capture.vault_sink_enabled)254
sink_path=$(resolve_pack_field capture.vault_sink_path) # relative to repo root256
if [ "$sink_enabled" != "true" ]; then257
: # disabled — skip silently258
elif { case "$sink_path" in /*|[A-Za-z]:*) sink_dir="$sink_path" ;; *) sink_dir="$REPO_ROOT/$sink_path" ;; esac; [ ! -d "$sink_dir" ]; }; then259
echo "[lintel/capture] WARN: vault_sink path not found: $sink_path — skipping vault export"260
audit_log capture vault_sink_skipped "reason=path_missing" "path=$sink_path"261
fi262
# A missing or disabled vault must NEVER fail CAPTURE — one-line warn, then move on.263
```265
When enabled and the path exists, write exactly ONE file per session,266
`<sink_path>/YYYY-MM-DD-<repo>-<short-slug>.md`:268
```markdown269
---270
created: YYYY-MM-DD271
tags: [session]272
type: session273
repo: <repo-name>274
branch: <git-branch>275
outcome: shipped | in-progress | blocked | exploration276
session: <cycle-id-if-available>277
---278
# <one-line session title>280
## What was done281
<3–8 lines, plain language, no code dumps>283
## Decisions284
<decisions taken, one line each; "None" if none>286
## Open threads287
<unfinished items / next steps; "None" if none>289
## Pointers290
- <repo-relative paths to the key files/PRs touched>292
## Links293
- [[<repo-name>]] <- the repo hub note (backlinks = per-repo session history)294
- [[<previous session note name>]] <- predecessor, if one exists for this repo295
```297
The frontmatter is a LOCKED flat schema (ADR-0007) — `sessions.base` (the Bases dashboard298
installed by `bin/li-vault-init`) and the vault's own skills query these exact properties.299
`outcome` uses the controlled vocabulary above, nothing else.301
**After writing the note, maintain the two navigation surfaces (same sink dir):**302
1. **Hub note** `<sink_path>/<repo-name>.md` — create a minimal one if missing (frontmatter:303
`created:`, `tags: [hub]`, `type: repo-hub`, `repo:`; one line of prose — same shape304
bin/li-vault-init writes). Never overwrite an existing hub.305
2. **Index** `<sink_path>/00-index.md` — create it if missing (frontmatter `type: session-index`306
+ one intro line), then maintain the list under its heading: carry the existing entries307
forward, PREPEND this session's line, truncate to 15:308
`- [[<note-name>]] - <one-line title> (<repo>)`. Keep frontmatter + intro intact; touch only309
the list. (Carrying forward the index's own lines is the one sanctioned vault read — never310
read other notes back.)312
Source the content from the Step 1 cycle aggregation. **Hard rules:** no secrets or tokens, no313
customer or employer-internal data, no full file contents — repo-relative pointers instead of314
payloads. Render the headings AND body in the session's working language (the template above is315
the canonical English form — translate it wholesale when the session ran in another language).316
Frontmatter must parse.318
**MANDATORY pre-write scan (battletest K4 — the vault note lands OUTSIDE the repo, where no319
git-commit hook sees it).** The "hard rules" above are not enough on their own — scan the320
rendered note body programmatically before writing, and ABORT the export (warn, never fail321
CAPTURE) on any hit:323
```bash324
source "$LINTEL_REPO_ROOT/hooks/shared/_patterns.sh"325
note_body="$(cat "$rendered_note")"326
sec_hits="$(scan_secrets all "$note_body")"327
pii_hits="$(scan_customer "$note_body")"328
if [ -n "$sec_hits$pii_hits" ]; then329
echo "[lintel/capture] WARN: vault export ABORTED — ${sec_hits:+secrets: $sec_hits }${pii_hits:+pii: $pii_hits}"330
audit_log capture vault_sink_skipped "reason=sensitive_content" "secrets=$sec_hits" "pii=$pii_hits"331
# skip the write entirely — do NOT sanitize-and-ship; an aborted export is correct332
else333
# write the note, then:334
audit_log capture vault_sink_written "file=<filename>"335
fi336
```338
### Step 8 — Retro (optional, light)340
Append to `.claude/memory/retros/<date>-<cycle-id>.md`:341
```yaml342
cycle_id: <id>343
duration_human: <hours>344
duration_cc: <minutes>345
tokens_used: <approx>346
cost_estimate_dollars: <X>348
what_worked:349
- <thing>350
what_friction:351
- <thing>352
next_time:353
- <pattern to repeat>354
- <pattern to avoid>355
```357
Not always written — only if cycle was substantial enough that retro adds value (operator-driven).359
### Step 9 — (removed in v5, ADR-0006)361
The operator-profile append (`~/.lintel/state/operator-profile.jsonl`) was a dead write — the362
promised SENSE read-back never existed. Subtracted. The granularity calibration record (Step 1b)363
is the real feedback loop and stays.365
### Step 10 — 00-state.md final entry367
Mechanical since v5.0 (ADR-0008) — one command, not a YAML obligation. No `next=`: the cycle is complete (`/li:resume` keys off `cycle_complete: true`); the full artifact list lives in the Step 11 closing message:369
```bash370
_sl="${LINTEL_SOURCE_ROOT:-${LINTEL_REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null)}}/lib/state.sh"371
[ -f "$_sl" ] || _sl="$HOME/.lintel/lib/state.sh"; source "$_sl" # installed by install.sh in consumer repos372
state_append CAPTURE DONE cycle_complete=true outcome=<DONE|DONE_WITH_CONCERNS|BLOCKED> lessons_captured=<count> adrs_drafted=<count> total_tokens=<N> cost_estimate=<$X>373
```375
### Step 11 — Closing message377
Tight closing — terse artifact list + operator-pattern observations, no motivational filler:379
```380
LINTEL CYCLE COMPLETE — <wedge title>382
Duration: <hours human / <minutes> CC383
Cost: $<X> | Tokens: <N>384
Outcome: <DONE / DONE_WITH_CONCERNS / BLOCKED>386
Artifacts produced:387
- Code: <commit range>388
- spec.md, plan.md, prompt.md (cold-executor trio)389
- Lessons captured: <N> (<N> promoted to Lintel global)390
- ADRs drafted: <N>391
- Customer deliverables: <list>393
Operator-pattern noted:394
- <specific observation 1>395
- <specific observation 2>396
- <specific observation 3>398
Next actions:399
- Trio is in <path> — ready for future cold-session re-execution400
- /li:resume picks up next cycle from here401
```403
## Status protocol405
- **DONE** — all artifacts written, profile updated406
- **DONE_WITH_CONCERNS** — captured but operator deferred ADR draft or lessons capture407
- **BLOCKED** — only if filesystem unavailable (rare)409
## Pause-points (mostly operator-confirms)411
- Per candidate lesson: AskUserQuestion capture / skip / edit412
- Per candidate ADR: AskUserQuestion draft now / draft later / skip413
- After trio drafted: AskUserQuestion "Verify with dogfood subagent?" (optional)414
- Role debrief (if active): AskUserQuestion "Update role file with these insights?"416
## Hop-in support418
YES — standalone post-implementation reflection. Useful if operator forgot CAPTURE in prior session.420
## Integration422
**Reads:**423
- All `.claude/runtime/state/00-state.md` entries from cycle424
- `.claude/runtime/state/build-log.md`425
- `.claude/runtime/state/review-report-*.md`426
- `.claude/runtime/state/compliance-report-*.md` (if the active pack defines compliance gates)427
- design doc, plan.md (DRAFT), spec.md (DRAFT)428
- selected work.json and optional swarm coordination/charter/brief/report/review evidence429
- Cycle's git diff for change scope430
- role file (if active)432
**Writes:**433
- `.claude/memory/lessons.md` (append per captured lesson)434
- `.claude/decisions/NNNN-<slug>.md` (new ADR if drafted)435
- `EVOLUTION-LOG.md` (if CLAUDE.md changed)436
- `spec.md` (FINALIZED from PLAN's draft)437
- `plan.md` (FINALIZED with post-verification status)438
- `prompt.md` (NEW — cold-executor handoff)439
- swarm work map and evidence artifacts (reaffirmed when the execution profile was selected)440
- `.claude/memory/retros/<date>-<cycle-id>.md` (optional)441
- `~/.lintel/roles/<id>.md` (update if role active + insights to add)442
- `.claude/runtime/state/00-state.md` (CAPTURE final entry)443
- `.claude/runtime/audit/cycle-completion.jsonl`444
- `.claude/runtime/audit/granularity.jsonl` (append — actual-vs-estimated calibration record, via `audit_log`; read by `lib/scale-estimator.sh` `scale_calibrated_prior`)445
- `<capture.vault_sink_path>/YYYY-MM-DD-<repo>-<slug>.md` (optional — vault sink, Step 7b; only if `capture.vault_sink_enabled: true` and the path exists)447
**Triggers:**448
- Nothing automatically — cycle complete449
- `/li:resume` available for next cycle450
- If part of multi-cycle engagement: next cycle starts at SENSE or DEFINE452
## Recommended agents454
- **ADRDrafter** (engineering/) — primary, ADR drafting455
- **ChangelogMaintainer** (engineering/) — release-note polish if SHIP didn't already456
- **DocWriter** (engineering/) — synthesize cold-executor trio prose457
- The active pack's voice gates (`resolve_pack_field voice.gates_active`; none by default) — if any CAPTURE artifact ships outside (rare)