index-atlas — ContextAtlas extraction via Claude Code session
When to use this skill
You're running ContextAtlas extraction inside your Claude Code
session. User invoked you via /index-atlas slash command directly,
OR via contextatlas project context surfacing in their session.
This is THE canonical entry point for subscription-bounded
extraction. The contextatlas CLI binary uses Anthropic API
direct extraction (different cost model; not this skill's concern).
Per ADR-02 v0.7 amendment §Decision: extraction has two entry
points; each entry point uses the appropriate cost model for its
invocation context.
If user is asking how to extract atlas.json:
- They're working in Claude Code session right now → invoke this skill
- They want CLI / CI/CD / scripting workflow → tell them to use
contextatlas indexfrom terminal (uses Anthropic API direct; requiresANTHROPIC_API_KEYenv var)
What this skill does
Substrate-equivalent extraction at /index-atlas surface per v0.7.1 Path D closure. Three MANDATORY phases (A → B → C). Do not advance until the prior phase substantively completes:
Phase A — Source-document walk via
contextatlas list- extraction-sourcesCLI Bash gate + manifest consumption via Read tool. Per-source enumeration discipline produces the full source registry across all three streams (ADRs + source-symbol docstrings + filtered commit messages) before any extraction call. Phase A IS the iteration discipline that closes the v0.7 Step 2.3.b.0 substrate-equivalence regression falsified at v0.8 Step 1.1.b factorial three-repo empirical.Phase B — Per-source extraction loop. For each source in the manifest, one canonical EXTRACTION_PROMPT invocation against the source content; aggregate per-source claims into atlas.json. The per-source iteration IS the mechanical floor — CLI's per- call API loop is its mechanical floor by construction; Phase B per-source reasoning loop is the subscription-bounded equivalent.
Phase C — Mandatory mechanical-floor CLI gates in order:
contextatlas validate-atlas(canonical schema) →contextatlas validate-extraction(depth-floor + coverage) →contextatlas resolve-symbols(LSP bridge) →contextatlas doctor(final verification). Each gate must exit 0 before advancing to the next.
This mirrors the v0.7 Step 2.3.c.0 generate-adrs closure pattern (cycle-execution observation 13 reproducibility) at the /index-atlas surface.
Canonical atlas schema (v1.4) — your output MUST match this
The atlas.json you write at workflow Phase B MUST conform exactly to
this shape. Mimic the structure below; the contextatlas validate-atlas mandatory gate (Phase C step 1) will reject any
deviation with specific remediation, and the workflow cannot
proceed until the atlas validates.
{
"version": "1.4",
"generated_at": "2026-05-13T20:00:00.000Z",
"generator": {
"contextatlas_version": "0.7.1",
"extraction_model": "claude-opus-4-7"
},
"source_shas": {
"docs/adr/ADR-01-name.md": "abc123def456...",
"src/router.ts": "fedcba789...",
"abc1234567890abcdef1234567890abcdef12345678": "abc1234567890abcdef1234567890abcdef12345678"
},
"symbols": [],
"claims": [
{
"source": "adr:ADR-01-name.md",
"source_path": "docs/adr/ADR-01-name.md",
"source_sha": "abc123def456...",
"severity": "hard",
"claim": "Brief architectural claim about the symbol(s)",
"rationale": "Why this claim matters architecturally",
"excerpt": "Direct quote from the source document",
"symbol_ids": [],
"symbol_candidates": ["SymbolName1", "SymbolName2"]
},
{
"source": "docstring:src/router.ts",
"source_path": "src/router.ts",
"source_sha": "fedcba789...",
"severity": "soft",
"claim": "Router invariant the docstring documents",
"rationale": "Why the documented contract matters",
"excerpt": "Direct quote from the docstring",
"symbol_ids": [],
"symbol_candidates": ["RegExpRouter"]
},
{
"source": "commit:abc1234567890abcdef1234567890abcdef12345678",
"source_path": "abc1234567890abcdef1234567890abcdef12345678",
"source_sha": "abc1234567890abcdef1234567890abcdef12345678",
"severity": "context",
"claim": "Architectural intent visible in commit message",
"rationale": "Why this intent matters going forward",
"excerpt": "Direct quote from commit body",
"symbol_ids": [],
"symbol_candidates": []
}
]
}
Schema invariants (MANDATORY)
- Top-level fields exactly:
version,generated_at,generator,source_shas,symbols,claims. Nothing else. Do NOT addcost_usd,cost_model,repo,sources, or any other top-level field. version: the string"1.4". Not"1". Not"1.3"(deprecated for new writes).generator: a structured object withcontextatlas_version+extraction_modelstring fields. NOT a free-form string like"contextatlas/index-atlas skill".claims: a flat top-level array. Each claim is one object with ALL the fields shown above. Do NOT nest claims inside asources: [{ claims: [...] }]structure — the canonical schema has claims at the top level and records each claim's source via the per-claimsource+source_path+source_shafields.claims[].sourceprefix conventions per stream:- ADR stream:
"adr:<basename>"(e.g.,"adr:ADR-01-name.md") - Docstring stream:
"docstring:<source_path>"(e.g.,"docstring:src/router.ts") - Commit stream:
"commit:<sha>"(full 40-char hex)
- ADR stream:
symbols: empty array at the time you write the atlas. Thecontextatlas resolve-symbolsPhase C step populates it via LSP walk.claims[].symbol_ids: empty array at the time you write the atlas. Phase C resolve-symbols populates it.claims[].symbol_candidates: the raw symbol names you extracted from the source document text. Phase C resolves them into the canonicalsymbol_idsarray. For Stream B docstring claims, ALWAYS include the documented symbol name as the first candidate (preserves provenance channel that CLI's writeDocstringClaim populates inline at pipeline.ts).severity: one of exactly"hard","soft","context". No other values.source_shas: full registry of every walked source. Keys are source identifiers (ADR repo-relative paths; source-file repo- relative paths; commit SHAs). Values are content SHAs from the manifest. Thevalidate-extractionPhase C gate cross-checks that every source_shas entry has at least one matching claim (silent-skip detection).
How extraction works
The extraction prompt is canonical to ContextAtlas — DO NOT modify
it. ContextAtlas owns the prompt per ADR-02 §Decision permitted-
modules invariant; this skill consumes the prompt via Read tool
against the .contextatlas/prompts/extraction.md artifact (Path-γ
Read-tool refactor per v0.7 Step 2.3.a.0).
Load the canonical prompt ONCE at the start of the skill via Read tool against:
.contextatlas/prompts/extraction.md (relative to cwd)
This file is generated by contextatlas init from the canonical
EXTRACTION_PROMPT constant at src/extraction/prompt.ts. The
user repo must have run contextatlas init before invoking this
skill (init copies the artifact from the installed contextatlas
package into .contextatlas/prompts/). If the file does not
exist at this path, instruct the user to run
contextatlas init before retrying.
DO NOT improvise an extraction prompt from training-data
familiarity. The legacy contextatlas show-prompt CLI subcommand
was removed entirely at v0.7 Step 2.3.b.0 — there is no
alternative path. Use Read tool against the artifact.
Phase A — Source-document walk (MANDATORY before Phase B)
Phase A produces the full source registry the Skill iterates in
Phase B. The CLI subcommand contextatlas list-extraction-sources
pre-walks all three streams via the same file-walker + LSP-symbol-
inventory + commit-message-extractor substrate the CLI extraction
pipeline uses; this guarantees substrate-equivalence at the source-
discovery layer (per Q1.1.G.α architectural framing in v0.7.1
ADR-02 amendment).
Phase A workflow steps
Invoke list-extraction-sources via Bash to walk all three streams and write the manifest to a known path:
contextatlas list-extraction-sources --output .contextatlas/extraction-sources.jsonNon-zero exit indicates a setup failure (missing config; adapter init failure; git not on PATH). Surface stderr to user with actionable remediation; do NOT proceed to Phase B.
Read the manifest via Read tool against
.contextatlas/extraction-sources.json. Verify shape:manifest_version: "1"sources.adrs— array of ADR entriessources.docstrings— array of symbol-with-docstring entriessources.commits— array of filtered commit entriessummary— per-stream counts
Enumerate the source registry mentally:
- Stream A:
manifest.summary.adr_countADRs to extract from - Stream B:
manifest.summary.symbols_with_docstringssymbols with docstrings to extract from - Stream C:
manifest.summary.filtered_commitsfiltered commits to extract from - Total source-extraction calls = sum of all three
- Stream A:
For refresh-case (existing
.contextatlas/atlas.json): Read the existing atlas.json via Read tool; capturesource_shasas the SHA-diff baseline; captureclaimsas the preserved-claims substrate. See "Refresh-aware workflow" section below for per-stream SHA-diff dispatch in Phase B.
Phase A complete when: manifest is loaded; you've enumerated total sources count per stream; (refresh-case) baseline atlas.json is read. Proceed to Phase B.
Phase B — Per-source extraction loop (MANDATORY)
Phase B is the load-bearing mechanical-floor enforcement at the Skill workflow boundary. Per-source iteration discipline:
One canonical EXTRACTION_PROMPT invocation per source-document. Each invocation is a separate reasoning loop producing JSON claims for that one source. DO NOT collapse multiple sources into a single mega-prompt; the per-source iteration IS the substrate-equivalence floor with CLI's per-call API loop.
RESPOND WITH JSON LITERAL DIRECTLY per source. Do NOT write a Python/JS/shell script to generate atlas.json by encoding claims as data literals. Reason through each source; produce the JSON as your direct textual response. Aggregate per-source JSON outputs into the final atlas.json at the end of Phase B.
Order: Stream A (ADRs) → Stream B (docstrings) → Stream C (commits). Process sources in manifest order within each stream.
Phase B step 1 — Stream A ADR extraction
For each adr in manifest.sources.adrs (cold-start: ALL ADRs;
refresh: only changed/new ADRs per refresh-aware workflow):
- Concatenate
EXTRACTION_PROMPT + adr.content + "\n---\n"(theEXTRACTION_PROMPTvalue was loaded at the start of the skill from.contextatlas/prompts/extraction.md). - Reason through the ADR content; produce JSON claims matching the per-claim schema in "Canonical atlas schema" above.
- For each claim, set:
source: "adr:" + path.basename(adr.path)(e.g.,"adr:ADR-01-name.md")source_path: adr.path(the repo-relative ADR path)source_sha: adr.shasymbol_ids: []symbol_candidates: [...]— extracted from ADR prose
- Validate the JSON parses + each claim has all required fields. Drop malformed claims (log warning); don't fail the whole run.
Phase B step 2 — Stream B docstring extraction
For each docstring in manifest.sources.docstrings (cold-start:
ALL symbols-with-docstrings; refresh: only docstrings whose
file_sha differs from baseline):
- Concatenate
EXTRACTION_PROMPT + docstring.docstring + "\n---\n". Thedocstring.docstringfield is the raw docstring TEXT pre- extracted bycontextatlas list-extraction-sourcesvia the LSP adapter'sgetDocstringAPI (matches CLIextractDocstringsForFilediscipline at pipeline.ts:846 exactly). - Reason through the docstring content; produce JSON claims.
- For each claim, set:
source: "docstring:" + docstring.source_path(e.g.,"docstring:src/router.ts")source_path: docstring.source_pathsource_sha: docstring.file_shasymbol_ids: []symbol_candidates: [docstring.symbol_name, ...other symbols the docstring mentions]— ALWAYS includedocstring.symbol_nameas the first candidate to preserve the provenance channel CLI'swriteDocstringClaimpopulates inline.
- Some docstrings won't surface architectural claims — that's expected; an empty claims array is fine. Don't fabricate.
Phase B step 3 — Stream C commit-message extraction
For each commit in manifest.sources.commits (cold-start: ALL
filtered commits; refresh: only commits whose sha is not in
baseline source_shas):
- Concatenate
EXTRACTION_PROMPT + commit.extraction_body + "\n---\n". Thecommit.extraction_bodyis pre-built perbuildCommitExtractionBody(subject + body) — matches CLI commit-message-extractor discipline exactly. - Reason through commit content; produce JSON claims.
- For each claim, set:
source: "commit:" + commit.shasource_path: commit.sha(the SHA serves as both source identifier and source-shas key)source_sha: commit.shasymbol_ids: []symbol_candidates: [...]— extracted from commit prose
Phase B step 4 — Aggregate + write atlas.json
After all three streams complete:
Build the unified atlas.json structure per the canonical schema above:
version: "1.4"generated_at: current ISO timestampgenerator:{ contextatlas_version, extraction_model: "claude-opus-4-7" }source_shas: full registry. Cold-start: aggregate of manifest sources (ADR paths → adr.sha; source-file paths → docstring.file_sha for files with extracted docstrings; commit SHAs → commit.sha for each extracted commit). Refresh-case: union of preserved baseline entries (unchanged sources) + newly-computed SHAs (changed + new sources); deleted-source entries removed.symbols: []claims: aggregate of all per-source claims emitted across all three streams. Refresh-case: union of preserved baseline claims (UNCHANGED sources) + newly-extracted claims (CHANGED- NEW sources); claims for DELETED sources dropped.
Persist via Write tool to
.contextatlas/atlas.json.Each claim's
source_shafield MUST match the corresponding hash insource_shasfor that source. Leavesymbols: []and eachclaims[].symbol_ids: []empty (Phase C resolve-symbols populates them).
Phase B complete when atlas.json contains claims from all
extracted manifest sources (subject to refresh-case skip
discipline) AND source_shas covers all walked sources.
Phase B expected wall-clock + session token guidance
Per-source iteration scales linearly with corpus size. Empirical calibration from CLI Stream A+B+C wall-clock at three reference repos (v0.8 Stage 2.a CLI baseline):
- hono (12 ADRs + ~280 symbols-with-docstrings + ~190 filtered commits): ~24 minutes CLI wall-clock equivalent
- httpx (10 ADRs + ~200 symbols-with-docstrings + ~3 commits): ~12 minutes CLI wall-clock equivalent
- cobra (11 ADRs + ~200 symbols-with-docstrings + ~7 commits): ~12 minutes CLI wall-clock equivalent
Skill subscription-bounded path consumes session tokens equivalently. Cohort UX framing: subscription-bounded extraction takes comparable wall-clock to CLI extraction at subscription budget cost vs API-bill cost.
If Phase B partially fails mid-iteration (network glitch; user
interrupt; tool error), the per-source idempotence pattern allows
resumption: re-invoke /index-atlas; refresh-aware workflow
captures partially-completed atlas.json as baseline; per-source
SHA-diff dispatches sources still needing extraction. Substantively
equivalent to CLI's incremental retry pattern.
Phase C — Mandatory mechanical-floor gates
After Phase B writes atlas.json, invoke FOUR mandatory CLI gates in order. Each gate must exit 0 before proceeding to the next.
Phase C step 1 — MANDATORY validate-atlas gate
contextatlas validate-atlas
If exit code is NON-ZERO, the atlas does NOT conform to canonical
schema. Read the stderr output (contains specific remediation for
each failing invariant — e.g., "Top-level generator must be an
object", "Top-level claims field missing — but a non-canonical
sources array was found instead"). Apply each remediation; re-
write the atlas.json; re-invoke contextatlas validate-atlas.
DO NOT proceed to step 2 until validate-atlas exits 0.
Phase C step 2 — MANDATORY validate-extraction gate (v0.7.1)
contextatlas validate-extraction
This gate enforces extraction-quality invariants beyond shape (per v0.7.1 Step 1.1.b.0 + Q1.1.G.α substrate-equivalence closure):
adr_claims_present: atlas has ≥1 claim withsource.startsWith("adr:"). Zero ADR claims indicates Phase B did not iterate Stream A — re-check Phase A manifest + re-execute Phase B step 1.adr_depth_floor: per-ADR claim count ≥ 8 (calibrated from v0.8 Stage 2.a CLI empirical three-repo mean ~12.6 claims/ADR; conservative floor at ~64% threshold). Below-floor ADRs indicate shallow Phase B extraction call — re-extract those ADRs.source_coverage: every entry insource_shashas ≥ 1 claim with matchingsource_path. Zero-claim sources indicate Phase B skipped sources mid-iteration — re-execute Phase B against the missing sources.
If exit code is NON-ZERO, read stderr (per-invariant remediation
guidance). Re-execute Phase B against the failing sources;
re-write atlas.json; re-invoke contextatlas validate-extraction.
DO NOT proceed to step 3 until validate-extraction exits 0.
Phase C step 3 — MANDATORY resolve-symbols invocation
contextatlas resolve-symbols
After validate-extraction exits 0, invoke contextatlas resolve-symbols. This CLI subcommand spawns LSP adapters, walks
the codebase, resolves each claim's symbol_candidates into
canonical symbol_ids via R8 name-form normalization, and writes
the enriched atlas back atomically. The atlas is INCOMPLETE
without this step — symbols[] remains empty and
claims[].symbol_ids stays unpopulated; downstream MCP query
tools (get_symbol_context, find_by_intent, impact_of_change)
cannot operate without resolved symbols. Report stdout output
verbatim to the user — it surfaces the resolved-claim count +
unresolved-candidate count. Zero API cost (local LSP subprocess
only).
Phase C step 4 — MANDATORY doctor verification
contextatlas doctor
After resolve-symbols completes, invoke contextatlas doctor and
report the output to the user. Specifically verify that:
atlas.has_symbolsreports PASS with a non-zero symbol countatlas.has_claimsreports PASS with a non-zero claim countatlas.schema_version_compatiblereports PASS
If atlas.has_symbols is FAIL, the workflow did NOT complete
successfully — go back and identify which step (resolve-symbols
likely) was skipped or failed; do not report success to the user
until doctor confirms the atlas substrate is canonical.
Substantive bash invocation rationale
The four Phase C Bash invocations (validate-atlas,
validate-extraction, resolve-symbols, doctor) are necessary
subprocess interactions — the CLI subcommands run schema
validation against TypeScript types, depth-floor + coverage
checks against atlas content, spawn LSP adapters, and inspect
filesystem state; none of which Read tool can substitute. The
Bash(contextatlas:*) allowlist covers all four. Unlike the
deprecated show-prompt / show-generate-prompt subcommands
(static content; removed at v0.7 Step 2.3.b.0 per Travis
foundational substrate-consistency framing), these invocations
are load-bearing for cross-path substrate equivalence with the
CLI extraction path.
Phase A also uses one Bash invocation (list-extraction-sources)
— same principled boundary: zero-API-cost local source walking
(file walker + LSP symbol inventory + git log filter) that Read
tool cannot substitute (LSP servers are dynamic subprocesses).
Refresh-aware workflow (cold-start vs incremental refresh)
/index-atlas is the canonical Skill entry point for BOTH first-
time atlas construction AND atlas refresh after code/ADR changes.
The workflow dispatches based on whether .contextatlas/atlas.json
already exists:
Cold-start case (no existing .contextatlas/atlas.json):
Full extraction across all three streams. Phase B iterates every
source in the manifest; populates source_shas with full
registry; writes atlas with all claims. No SHA-diff gating
applies because there is no baseline to compare against.
Refresh case (existing .contextatlas/atlas.json):
Phase 4 SHA-diff incremental extraction per ADR-12 substrate.
Phase A reads both the manifest (current state) AND the existing
atlas.json (baseline). Phase B dispatches per source per stream:
Stream A (ADRs) — for each
adrin manifest.sources.adrs:- If
baseline.source_shas[adr.path] === adr.sha(UNCHANGED): SKIP extraction; preserved claims with matchingsource_path === adr.pathcarry forward unchanged. - If
baseline.source_shas[adr.path] !== adr.shaOR adr.path absent from baseline (CHANGED or NEW): EXTRACT via Phase B step 1.
- If
Stream B (docstrings) — for each
docstringin manifest.sources.docstrings:- If
baseline.source_shas[docstring.source_path] === docstring.file_sha(UNCHANGED file): SKIP extraction; preserved claims with matchingsource_path === docstring.source_pathcarry forward. - If
baseline.source_shas[docstring.source_path] !== docstring.file_shaOR source_path absent from baseline (CHANGED or NEW file): EXTRACT via Phase B step 2 for ALL docstring entries from that file. - File-granularity SHA-diff mirrors CLI's per-file extraction idempotence at pipeline.ts; changing one symbol in a file re-extracts all symbols in that file (cheaper than per- symbol SHA tracking).
- If
Stream C (commits) — for each
commitin manifest.sources.commits:- If
commit.shais present as a key inbaseline.source_shas(already extracted): SKIP; preserved commit claims with matchingsource_path === commit.shacarry forward. - If
commit.shais absent (new filtered commit since last refresh): EXTRACT via Phase B step 3.
- If
Deleted sources — for any key in
baseline.source_shasthat does NOT appear in the current manifest (deleted ADR; deleted source file; truncated git history): drop its preserved claims from the refresh; remove its entry fromsource_shas.Aggregate at Phase B step 4 — final atlas is the union of: (a) preserved baseline claims for UNCHANGED sources, (b) newly-extracted claims for CHANGED + NEW sources, with (c) baseline claims for DELETED sources dropped.
source_shasis the union of preserved entries (UNCHANGED) + newly-computed SHAs (CHANGED + NEW), with deleted-source entries removed.
This mirrors the CLI's contextatlas index Phase 4 SHA-diff
extraction pattern (per ADR-12 substrate) and substantively bounds
refresh cost — cohort users re-running /index-atlas after a
single ADR edit pay only the extraction cost for the one changed
document, not the full corpus.
Cost model
Claude Code session tokens (subscription-bounded). Reports
cost_usd: 0.0 + cost_model: "subscription-bounded" in the
extraction summary written to atlas.json metadata. No Anthropic
API key required. Per ADR-02 v0.7 §Consequences cost-accounting-
reflects-entry-point lock.
Cohort UX framing: subscription-bounded extraction takes comparable wall-clock to CLI extraction at subscription budget cost (no API bill). Session token consumption scales linearly with corpus size — see Phase B "expected wall-clock + session token guidance" section above for empirical anchors per reference repo.
Tool usage
This skill uses Claude Code session tools to perform extraction:
- Read for the canonical extraction prompt artifact
(
.contextatlas/prompts/extraction.md); the Phase A manifest (.contextatlas/extraction-sources.json); refresh-case existing atlas (.contextatlas/atlas.json) - Write for
.contextatlas/atlas.jsonpersistence (claims-only stub state in canonical AtlasFileV1 v1.4 shape per "Canonical atlas schema" section above) - Bash for:
- Phase A (MANDATORY):
contextatlas list-extraction-sources --output .contextatlas/extraction-sources.json— walks all 3 streams via existing main-repo walker substrate; emits JSON manifest for Skill consumption - Phase C step 1 (MANDATORY):
contextatlas validate-atlas— canonical schema verification; non-zero exit triggers fix + re-validate loop - Phase C step 2 (MANDATORY; v0.7.1):
contextatlas validate-extraction— depth-floor + coverage verification; non-zero exit triggers Phase B re-execution against failing sources + re-validate loop - Phase C step 3 (MANDATORY):
contextatlas resolve-symbols— LSP bridge; atlas is INCOMPLETE without this step - Phase C step 4 (MANDATORY):
contextatlas doctor— final verification; atlas.has_symbols PASS required
- Phase A (MANDATORY):
The Bash(contextatlas:*) allowlist covers all five invocations.
Bundled helper scripts deferred to v0.8+ per v0.7 ship scope.
Failure modes
.contextatlas/prompts/extraction.mdmissing: user has not runcontextatlas initin this repo (or init failed to copy artifacts). Surface remediation: instruct user to runcontextatlas initand retry. Do NOT improvise the prompt.contextatlas list-extraction-sourcesexits non-zero (Phase A gate): setup failure (missing config; adapter init failure; git not on PATH). Read stderr for actionable remediation; do NOT proceed to Phase B. Common cases: LSP peer dependencies missing (npm installcontextatlas peer deps); non-git working tree (Stream C silently empty — that's fine, but stderr surfaces it).- Manifest shape unexpected: if the Read manifest doesn't
match the
manifest_version: "1"expectation, surface the gap to the user and stop. Substrate-currency between list-extraction-sources output and Skill consumption is load- bearing; manifest version mismatch indicates a deployment skew. contextatlas validate-atlasexits non-zero (Phase C step 1 gate): read stderr carefully — it contains specific remediation for each failing schema invariant. Apply each remediation; re-write the atlas.json; re-invokecontextatlas validate-atlas. DO NOT proceed to step 2 until validate-atlas exits 0.contextatlas validate-extractionexits non-zero (Phase C step 2 gate; v0.7.1): read stderr per-invariant remediation; identify failing invariant(s); re-execute Phase B against the failing sources (e.g., re-extract shallow ADRs; re-iterate skipped sources); re-write the atlas.json; re-invokecontextatlas validate-extraction. DO NOT proceed to step 3 until validate-extraction exits 0.contextatlas resolve-symbolsexits non-zero: surface stderr output to user with remediation guidance. Common cases: LSP adapter init failed (peer dependencies missing —npm installcontextatlas peer deps); atlas malformed (re-validate via validate-atlas); config invalid (runcontextatlas doctorto diagnose). User can re-invokecontextatlas resolve-symbolsmanually after fixing the issue.contextatlas doctorreportsatlas.has_symbolsFAIL (Phase C step 4 verification): resolve-symbols was likely skipped or failed silently. Go back to Phase C step 3 and re-invoke. Do NOT report Skill workflow success to the user while atlas.has_symbols reports FAIL.- Source document missing mid-Phase-B: log warning; skip the document; continue. Phase A produced the manifest snapshot; if a source disappears between Phase A and Phase B (rare; race condition), graceful skip is correct behavior.
- Malformed JSON output from per-source reasoning: log warning with first 200 chars of output; skip that source's claims; continue. Per-source failure is bounded — other sources' claims preserved.
- Schema validation failure on per-claim shape: drop malformed claims (per-claim granularity); log warning; preserve valid claims from same source. validate-atlas Phase C gate catches any aggregate shape violations downstream.
- Persistence write failure (Phase B step 4): fail loudly per CLAUDE.md "actionable error messages" discipline; surface error to user.
- Phase B partial completion + Skill interrupt: subsequent
/index-atlasinvocation hits the refresh-aware case; preserved claims from the partially-written atlas.json carry forward via SHA-diff baseline; only un-extracted sources re-execute. Per- source idempotence preserved.