원클릭으로
archive-callouts
Sweep addressed callouts older than a threshold (default 180 days) into the target note's
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Sweep addressed callouts older than a threshold (default 180 days) into the target note's
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Generate a concise 1-page investment brief from a thesis — the elevator pitch version. Use when user says "brief", "summarise thesis", "pitch me [TICKER]", "one-pager", or "investment memo".
Side-by-side competitive comparison of two or more companies. Use when user says "compare", "X vs Y", "which is better", or asks about competitive dynamics between specific companies.
Targeted deep research to fill a specific gap in an existing thesis. Use when user says "deepen", "flesh out", "expand on", "fill in", or specifies a thesis section to improve.
Rebuild the vault dependency graph (_graph.md) via the deterministic generator script. /graph forces a full rebuild; /graph last (run after every /sync) rebuilds only if the vault changed; /graph [N] is treated as last. The generator reads the vault and writes _graph.md directly, so the file never streams through a model response.
Ingest content into the vault as structured research notes. Accepts a URL, a local file path, or no arguments (batch-processes _Inbox/). Use when user shares a URL, says "clip this", "ingest", or "process inbox".
Run health checks on the vault for inconsistencies, stale data, orphaned notes, and missing connections. Use periodically or when user says "lint", "health check", or "audit".
| name | archive-callouts |
| description | Sweep addressed callouts older than a threshold (default 180 days) into the target note's |
| model | sonnet |
| effort | max |
| allowed-tools | Read Grep Glob Edit Write Bash(date * cp * mkdir * grep * rm * awk *) |
Follow CLAUDE.md Writing Standards strictly. No hedge words, lead with insights/numbers, tables over prose, every sentence must earn its place.
Sweep addressed callouts older than the configured threshold from their original sections into a dedicated ## Legacy Callouts archive section at the bottom of the target note (above ## Log). Callout formatting is stripped — entries become plain bulleted text preserving full original body, date metadata, section provenance, and Response. The source sections become less cluttered over time; the audit trail stays co-located with the thesis.
Tier 1 skill under CLAUDE.md Change Safety Rules — owns the ## Legacy Callouts section exclusively. Nothing else writes to it; this skill never writes anywhere else except the per-thesis ## Log (append-only Callout sweep: entry) and thesis frontmatter (last_callout_sweep:).
$ARGUMENTS patterns:
180, 90) → execute vault-wide sweep with that day threshold.TICKER (e.g., NVDA) → scoped dry-run preview for one thesis at default 180d.TICKER [days] (e.g., NVDA 90) → scoped execute.[days] dry-run or TICKER [days] dry-run → explicit dry-run even with numeric threshold (belt-and-braces).Parse order:
Split $ARGUMENTS by whitespace into tokens.
If any token is "dry-run" → force dry-run mode, strip it.
Classify each remaining token by CHECKING THE VAULT, not a regex:
- If Glob "Theses/<token> - *.md" matches a file → ticker (scoped).
Vault-check (not a charset regex) is mandatory: the vault has numeric and
alphanumeric tickers (000660, 2383, 285A, 6857) and hyphenated ones
(BTC-CRYPTO) that a /^[A-Z].../ pattern cannot match — misparsing "2383"
as a 2383-day threshold silently promotes a scoped dry-run into an
UNCONFIRMED VAULT-WIDE EXECUTE.
- Else if token matches /^\d+$/ → integer threshold (days).
- Else → unrecognized token. Report `❌ Unrecognized argument "<token>" — not a
thesis ticker (no Theses/<token> - *.md) and not an integer threshold.` Abort.
Do NOT silently fall through to vault-wide execute.
Default threshold = 180.
No numeric threshold AND no explicit execute intent → dry-run mode.
When ambiguous: a bare integer with no matching thesis (e.g., 100 — no Theses/100 - *.md) is a threshold. A token that matches a thesis glob (e.g., 2383 → Theses/2383 - Elite Material.md) is that ticker. The vault-glob check resolves the ambiguity deterministically against real files.
Per .claude/skills/_shared/preflight.md Procedure 1.
vault-wide scope. Timeout budget: 10 minutes (may touch many theses + sector notes).TICKER): ticker:TICKER scope. Timeout budget: 5 minutes.Capture the token. Verify ownership (Procedure 1.5) at every subsequent Bash block. Release in the final reporting block.
Per .claude/skills/_shared/preflight.md Procedure 2.
.rename_incomplete.*. If any exist, hard-block — a sweep mid-rename could reformat a thesis whose inbound wikilinks are still split across old and new names, compounding the inconsistency..rename_incomplete.TICKER. Hard-block if present.Unlike /deepen (which aborts on missing sections), /archive-callouts creates ## Legacy Callouts on demand per the Sweep Contract below. Standard Procedure 4 does NOT apply to this skill.
The skill DOES require ## Log to exist on the target note (needed for the Callout sweep: append). If ## Log is absent → skip the target with warning ℹ️ Skipped [[target]]: no ## Log section. Sweep needs Log for audit trail. Add ## Log manually or ignore if target is free-form macro.
Both applicable pre-flight checks must pass before proceeding to Phase 1.
Resolve the list of target files.
Theses/*.md + Sectors/*.md + Macro & Technology/*.md. Research/ is excluded (Tier 2 immutable per CLAUDE.md — research notes don't carry callouts by convention).TICKER): single file Theses/TICKER - *.md resolved via Glob.
❌ No thesis matching ticker "[TICKER]". Check the ticker spelling or use /thesis TICKER to create. Abort.Report the resolved scope to the user:
Scope: [N] theses + [M] sectors + [K] macro notes
Threshold: [days] days from → Addressed date
Mode: [dry-run | execute]
For each target file, issue ONE Read. Parse the body for callout blocks. Execute the following parallel scan pattern for efficiency:
Issue a single parallel batch of Read calls for ALL resolved target files. Wait for all to land. Do not serialize.
For each file's content, identify callout blocks matching this pattern (line-anchored):
> [!<type>] <fresh_date>[ → Addressed <addressed_date>][ <markers>]
> <body line 1>
> <body line 2>
...
> **Response:** <response line 1>
> <response line 2>
...
Where:
<type> is one of question | error | tip | todo (exactly — any other value → log ℹ️ Skipped unrecognized callout type "[X]" in [file] and ignore)<fresh_date> is YYYY-MM-DD<addressed_date> is optional. Absent → callout is fresh → SKIP (never sweep fresh)<markers> may include [[pinned]] — opt-out marker, applies to fresh OR addressed callouts → SKIP. (Note: [[preserve]] is deprecated as of 2026-04-29 — [[pinned]] replaces it. The skill still treats [[preserve]] as a skip during a transition window for safety, but /lint #56 flags any remaining occurrences for migration.)**Response:** block must be present for a callout to qualify as addressedParent section detection: walk backward from the callout's opening line to the nearest preceding ## <section_name> heading. This is the callout's origin section — captured for the Legacy entry. If the callout sits above all ## headings (shouldn't happen in theses, unusual in sector notes), label section as <unknown>.
Age computation: age_days = today - addressed_date. Callouts with age_days >= threshold AND without [[pinned]] (and without legacy [[preserve]] during the transition window) → sweep candidates.
Location safety: callouts inside ## Legacy Callouts itself must NEVER be parsed. Callouts inside ## Log must also be skipped (Log entries never contain callouts by convention; defensive filter). Skip the entire section bodies for these two headings during scan.
Convert internal Obsidian callout types to human-readable labels used in the Legacy entry:
| Callout type | Legacy label |
|---|---|
question | question |
error | warning |
tip | tip |
todo | todo |
Note: error maps to warning because the template file is user-warning.md (user-facing vocabulary matches the hotkey label, not the Obsidian internal type). Consistent with CLAUDE.md convention.
For each sweep candidate, build the Legacy entry text:
- **<addressed_date>** · <legacy_label> · <parent_section> · raised <fresh_date> → <body_joined>
- **Response:** <response_joined>
Where:
<body_joined> = all body lines joined with a single space. Preserve inline formatting (bold, italics, wikilinks). Strip the leading > quote prefix from each line.<response_joined> = Response block content joined the same way. Strip the **Response:** prefix from the first line; the constructed sub-bullet re-adds **Response:** cleanly.Sub-bullet uses 2-space indent (matching CLAUDE.md markdown convention).
ALWAYS emit the preview — both dry-run and execute modes produce this table. Execute mode then proceeds to Phase 4; dry-run stops here.
Per-file preview table:
### Sweep preview — threshold: [days] days
| File | Candidates | Preserved | Pinned | Fresh | Oldest addressed | Sections touched |
|------|-----------|-----------|--------|-------|------------------|-------------------|
| Theses/NVDA - Nvidia.md | 14 | 2 | 1 | 3 | 2025-08-15 | Bull Case (6), Catalysts (4), Industry Context (3), Risks (1) |
| Theses/BESI - BE Semiconductor.md | 6 | 0 | 0 | 1 | 2025-09-22 | Industry Context (4), Bull Case (2) |
| Sectors/Semiconductors.md | 3 | 1 | 0 | 0 | 2025-07-01 | Competitive dynamics (2), Macro shifts (1) |
Totals: 23 candidates across 3 files | 3 preserved | 1 pinned | 4 fresh (skipped)
Column semantics:
[[pinned]] marker → would be swept.[[pinned]] — skipped regardless of age. Persistent revisit slot.[[pinned]] — never eligible (not in scope for sweep).[[preserve]] markers (deprecated 2026-04-29) are still honored as skips during the transition window; surfaced as a separate column when present, with a migration hint.If zero candidates anywhere: No callouts eligible for sweeping. Threshold [days]d reached zero addressed callouts across [N] files. Nothing to do. Stop (both dry-run and execute modes exit cleanly).
Dry-run mode terminates here — no snapshots, no writes, no Log entries. Report: ℹ️ Dry-run complete. Re-run without dry-run flag to execute.
Generate HHMMSS once at Phase 4 entry:
HHMMSS=$(date +%H%M%S)
TODAY=$(date +%Y-%m-%d)
BATCH_ID="callout-sweep-$TODAY-$HHMMSS"
Reused across all per-thesis snapshots in this run so /rollback can cascade.
For each file with ≥1 candidate, issue ONE Bash block with parallel cp + wait:
mkdir -p _Archive/Snapshots
pids=()
cp "Theses/NVDA - Nvidia.md" "_Archive/Snapshots/NVDA - Nvidia (pre-callout-sweep $TODAY-$HHMMSS).md" & pids+=($!)
cp "Theses/BESI - BE Semiconductor.md" "_Archive/Snapshots/BESI - BE Semiconductor (pre-callout-sweep $TODAY-$HHMMSS).md" & pids+=($!)
cp "Sectors/Semiconductors.md" "_Archive/Snapshots/Semiconductors (pre-callout-sweep $TODAY-$HHMMSS).md" & pids+=($!)
# Bare `wait` returns 0 even if a background cp failed — wait on each PID so a
# failed snapshot is actually detected (§4.2 hard-abort depends on this).
snap_fail=0
for pid in "${pids[@]}"; do wait "$pid" || snap_fail=1; done
[ "$snap_fail" -ne 0 ] && { echo "❌ snapshot cp failed — aborting Phase 4 (no transformations applied)"; exit 1; }
Then, in one parallel Edit batch, add snapshot frontmatter to each new snapshot:
snapshot_of: "[[<original path>]]"
snapshot_date: <TODAY>
snapshot_trigger: callout-sweep
snapshot_batch: <BATCH_ID>
/rollback trigger allowlist recognizes callout-sweep per the updated rollback SKILL.md.
If any cp fails → hard-abort Phase 4 entirely. Do NOT proceed to 4.3 with partial snapshots. Report the failure and release the lock.
For each file with candidates, execute the following steps atomically. If any step within a file fails, abort that file and proceed to the next; partial-file recovery uses the snapshot created in 4.2.
For each sweep candidate in the file, use Edit to delete the entire callout block from the body. The block spans from > [!<type>] header line through the last > quoted line before the next non-> line.
Block boundary precision: the block is ONLY the contiguous > -prefixed lines. The trailing blank line AFTER the block (between the callout and the next content) is NOT part of the block — do not include it in old_string. Obsidian renders tightly-packed callouts without intervening blanks; the surrounding blank line is surrounding text, not block structure. Including the trailing blank in the deletion collapses legitimate paragraph separators.
Edit strategy — primary path (unique blocks): old_string = <full callout block WITHOUT trailing blank line>, new_string = "". Edit each candidate one-by-one (parallel Edits on the same file are not safe).
Edit strategy — retry path (silent failure): after each Edit, re-grep the file for > [!<type>] <fresh_date> exact header. If still present → Edit silently failed. Retry with expanded context: include 1 line before and after the block in old_string (and mirror in new_string to preserve those lines).
Edit strategy — fallback path (byte-identical blocks): if retry fails AND a grep reveals ≥2 matches of the block header in the file (indicating the callout was copy-pasted and multiple byte-identical blocks exist):
[header_line_num, last_quoted_line_num]).Write of the filtered body back to the file path. This bypasses Edit's uniqueness requirement entirely — line numbers disambiguate identical content.Second failure on non-duplicate case: if Edit retry fails AND grep shows exactly 1 match still present (genuine silent-failure mystery, not a duplicate-content issue) → abort this file, snapshot restore path available via /rollback. Continue to next file in batch.
Why a file-level Write fallback is safe: Phase 4.2 created a per-file snapshot BEFORE any 4.3 edits. A Write-based rewrite is no more destructive than the Edit-based approach — both fully control the file's final state. Snapshot-based rollback works identically either way.
## Legacy Callouts sectionRead the file's current state after 4.3a. Locate ## Legacy Callouts heading:
Case A: Section absent
Insert a new ## Legacy Callouts block above ## Log:
## Legacy Callouts
<!-- Auto-managed by /archive-callouts. Addressed callouts older than the sweep threshold (default 180 days) are moved here from their original sections as plain bulleted entries: `- **<addressed-date>** · <type> · <section> · raised <fresh-date> → <body>` with a `**Response:**` sub-bullet. Sorted descending (newest first). Do NOT hand-edit. To exempt a callout from sweeping, add `[[pinned]]` to its header in-place. -->
<new entries sorted descending by addressed_date>
## Log
Edit anchor: old_string = "## Log\n", new_string = "## Legacy Callouts\n<!-- ... -->\n\n<new entries>\n\n## Log\n".
Case A fallback: if ## Log is absent, Phase 0.3 already skipped this file. Should not reach here.
Case B: Section present
Merge new entries into the existing list, maintaining descending sort by the leading **YYYY-MM-DD** date (newest first). Re-render the entire section bullet list in sorted order.
Edit anchor: find the section's bullet list (every line starting - **YYYY-MM-DD** and any sub-bullet indented 2 spaces). Replace the full list with the merged-and-sorted list. Preserve the section heading and comment unchanged.
Stable tie-break: if two entries share the same addressed date, sort by raised date descending second, then by original position third (preserve scan order).
Malformed existing entries — preservation-in-place contract:
When parsing existing ## Legacy Callouts entries for sort-merge, an entry is malformed if ANY of the following holds:
**YYYY-MM-DD** at bullet start)**2026-0i-15**, **26-04-15**, non-ISO format)raised YYYY-MM-DD token**Response:** sub-bullet with 2-space indentHandling:
/lint #52 will flag them).<!-- malformed — see /lint #52 --> HTML comment on the line directly above the bullet, insert one. Do NOT modify the entry itself. Idempotent: if the comment already exists, don't duplicate.⚠️ N malformed legacy entries preserved in-place; run /lint #52 for details when applicable.Rationale: malformed entries indicate prior hand-editing or a partial-write failure on an earlier sweep. Neither scenario justifies aborting the current sweep or silently reformatting user edits. Surface them to /lint, sort the clean entries, proceed.
Edit anchor for Case B merge:
old_string = the current section's bullet list verbatim (every - **... line and all 2-space-indented sub-bullets, up to but not including the blank line before ## Log)new_string = the malformed-entries block (with <!-- malformed --> annotations) followed by a blank line followed by the sorted clean listIf the merged output is byte-identical to the current list (no new candidates AND no malformed-annotation inserts needed), skip the Edit entirely (no-op). Log: ℹ️ [file] Case B no-op — no merge required.
Append to the file's ## Log section a new dated entry:
### <TODAY>
- Callout sweep: <N> addressed callouts ≥<days>d swept to ## Legacy Callouts. Sections touched: <breakdown>. Safety snapshot: [[_Archive/Snapshots/<filename> (pre-callout-sweep <TODAY>-<HHMMSS>)]]
Where <breakdown> matches the Phase 3 table format: Bull Case (6), Catalysts (4), ....
Edit strategy — two cases:
Before editing, grep the file for a ### <TODAY> header within the ## Log section. Two outcomes determine the Edit anchor.
Case 4.3c.A: no ### <TODAY> header in ## Log today — append a new dated section.
The Log section is always the LAST section of the file (per Thesis/Sector template canonical order). Append at end-of-file is safe.
old_string: the last non-empty line of the current file body (after Phase 4.3a/4.3b edits have landed). Read the file's tail to find it — typically this is the last bullet of the most recent Log entry, or the ## Log heading itself if the section is empty.new_string: <old_string>\n\n### <TODAY>\n- Callout sweep: ...\nAnchor uniqueness concern: if the file's last line happens to be text that appears multiple times elsewhere (rare but possible), expand the anchor to include 2-3 preceding lines until unique.
Case 4.3c.B: ### <TODAY> header already exists in ## Log today — append bullet under existing header.
Another skill already wrote a Log entry today. Tier 2 append-only: NEVER re-order, NEVER create a second same-day header, NEVER insert between existing bullets.
old_string: find the LAST bullet line under today's date header. Walk from ### <TODAY> downward until either (a) the next ### date header, (b) the next ## section heading, or (c) end of file. The line immediately before that boundary is the last bullet.new_string: <old_string>\n- Callout sweep: ...Verification: after the Edit, re-grep the Log section for the new bullet. If absent → Edit silently failed. Retry with expanded context (include the date header + all existing same-day bullets in old_string). Second failure → abort this file's Log append only; the 4.3a/4.3b edits have already landed. Report: ⚠️ [file] Phase 4.3c Log append failed — body changes persist, audit trail missing. /lint #53 will flag. Manual fix: append "Callout sweep: ..." bullet to ## Log section under today's date.
If ## Log is absent entirely — Phase 0.3 already skipped this file. Should not reach here. If reached (state corruption mid-skill), hard-abort this file with snapshot-restore recommendation.
Log prefix Callout sweep: is registered in _shared/log-prefixes.md entry #17 as skill-origin (drift-exclusion, propagation-skip per /sync Step 2.5 and Step 3e).
Add or update last_callout_sweep: <TODAY> in the file's frontmatter.
Edit strategy: if field exists, Edit replaces the value. If absent, insert before the closing --- of the YAML block.
For each swept file, run ONE Bash probe:
for f in [swept files]; do
echo "=== $f ==="
# grep -cE (extended regex): the `{4}` interval quantifier is a LITERAL in BRE
# (plain grep -c), so the prior probe matched nothing and always printed 0 → the
# "dropped by exactly the candidate count" check passed even when 4.3a Edits
# silently failed. -cE fixes the quantifier; `grep -c` already prints 0 on no
# match, so the `|| echo 0` (which double-printed) is dropped.
echo -n "Swept callouts remaining: "
grep -cE "^> \[!.*\] [0-9]{4}-[0-9]{2}-[0-9]{2} → Addressed [0-9]{4}-[0-9]{2}-[0-9]{2}" "$f"
echo -n "Legacy Callouts entries: "
awk '/^## Legacy Callouts/,/^## Log/' "$f" | grep -c "^- \*\*[0-9]"
echo -n "Today's Callout sweep entry present: "
grep -cE "^- Callout sweep:.*$(date +%Y-%m-%d)" "$f"
done
Expected: for each file, swept-callouts-remaining should have dropped by exactly the candidate count, Legacy Callouts entries should have grown by exactly the candidate count, sweep Log entry should be 1.
On any mismatch: report ⚠️ Verification failed for [file]: expected [N] swept / got [actual]. Snapshot available at [[path]]. Review and consider /rollback. Do NOT try to self-heal — snapshot restore is the correct path.
## Callout sweep complete — threshold: [days] days
Run ID: [BATCH_ID]
Files modified: [N]
Callouts swept: [total]
Preserved (opt-out): [count]
Pinned (skipped by design): [count]
Fresh (not eligible): [count]
Verification: all passed | [list failures]
| File | Swept | Sections | Snapshot |
|------|-------|----------|----------|
| Theses/NVDA - Nvidia.md | 14 | Bull Case (6), ... | [[_Archive/Snapshots/NVDA - Nvidia (pre-callout-sweep ...)]] |
→ Run /graph last to refresh wikilink adjacency ([[pinned]] markers won't trigger broken-link flags — already in allowlist).→ Run /lint to verify Legacy Callouts schema (checks #50-#53).→ To undo a specific file's sweep: /rollback [ticker or note name] → select (pre-callout-sweep ...) snapshot.→ To undo the whole run: /rollback [BATCH_ID] → cascade (a) restores every file to pre-sweep state in one transaction.Final Bash block verifies ownership and releases:
# LOCK_FILE MUST match the scope acquired at 0.1: `.vault-lock` for vault-wide,
# `.vault-lock.TICKER` for scoped. Hardcoding `.vault-lock` stranded every scoped
# run's `.vault-lock.TICKER` until its timeout (blocking follow-on ticker skills).
LOCK_FILE="<paste-lockfile-path-captured-from-Step-0.1>" # .vault-lock OR .vault-lock.TICKER
EXPECTED_TOKEN="<paste-token-captured-from-Step-0.1>"
if [ -f "$LOCK_FILE" ] && grep -q "token: $EXPECTED_TOKEN" "$LOCK_FILE"; then
rm -f "$LOCK_FILE" && echo "=== LOCK RELEASED ($LOCK_FILE) ==="
else
echo "⚠️ Lock ownership check failed at release — skipping rm to avoid stealing another skill's lock."
fi
Runs unconditionally (same pattern as /clean, /deepen) — dry-run, execute, and abort paths all release.
These invariants define what /archive-callouts guarantees. Consumer skills (/sync, /brief, /lint, /rollback, /graph) depend on them; do not break without updating every consumer:
## Legacy Callouts is owned exclusively by /archive-callouts. No other skill writes to this section. Users should not hand-edit (but the skill tolerates structural damage by re-sorting and re-validating on next sweep; /lint #52 + #53 catch irrecoverable damage).## Log unambiguously. The skill creates it there. /lint #53 flags out-of-position sections as Nice to Have.- **YYYY-MM-DD** · <type> · <section> · raised YYYY-MM-DD → <body> + **Response:** sub-bullet. /lint #52 enforces._Archive/Snapshots/, (b) last_callout_sweep: frontmatter, (c) Callout sweep: Log entry in ## Log. No sector propagation, no macro propagation, no _hot.md update, no _graph.md update.[[pinned]] is the opt-out marker (replaces deprecated [[preserve]] 2026-04-29). Any callout with [[pinned]] — fresh or addressed — NEVER sweeps regardless of age. Added by user in-place, never authored by the skill. During the deprecation transition window the skill also honors [[preserve]] as a skip; /lint #56 flags any remaining occurrences for migration.[[pinned]] are invisible to sweep. Only addressed callouts (with → Addressed YYYY-MM-DD token) are candidates. Pinned addressed callouts skip sweep by marker; pinned fresh callouts are also exempt (and not in scope anyway because they're unaddressed).Callout sweep:. Registered in _shared/log-prefixes.md §17 as skill-origin drift-exclusion. Producer drift here breaks /sync Step 2.5 and Step 3e silently.callout-sweep (hyphenated). /rollback recognizes this in its 2.5c non-manifest cascade path. Changing the trigger name without updating rollback breaks the cascade-by-batch-id lookup.| Failure | Recovery |
|---|---|
Snapshot cp fails in 4.2 | Phase 4 aborts before any file edits. Lock releases. No damage. Re-run after resolving disk/permission issue. |
| Edit fails in 4.3a (callout removal) | That file's sweep aborts mid-transform. Per-file snapshot exists at _Archive/Snapshots/[file] (pre-callout-sweep ...). Restore via /rollback. Other files in the batch are unaffected. |
| Edit fails in 4.3b (Legacy Callouts insertion) | Same as above — per-file snapshot restores the state before 4.3a ran. |
| Edit fails in 4.3c (Log append) | Thesis has Legacy Callouts populated but no audit trail. /lint #53 catches (Legacy entries without matching Log entries). Manual fix: append Log entry per Phase 4.3c format, or /rollback to pre-sweep snapshot. |
| Edit fails in 4.3d (frontmatter) | Sweep is body-complete; only hygiene metadata is stale. /lint #50 surfaces missing last_callout_sweep: on next run. Low severity. |
| Verification probe mismatch in 4.4 | Reported to user. No self-heal. Snapshot restore via /rollback. |
Lock ownership lost mid-run (LOCK_STOLEN) | Abort immediately. Report files already swept (completed 4.3 sequences) + files abandoned. User decides: keep partial progress, or /rollback the batch. |
Design rationale lives in .claude/skills/archive-callouts/RATIONALE.md:
_Archive/Callouts/*.mdwarning label for [!error] callout type