Load-bearing files
This is the lookup reference. For each load-bearing piece: WHERE it lives, WHAT it is, and WHAT fails if it’s missing or wrong.
For how the pieces fit together conceptually, see The discipline stack. To set up a new project, see Set up a new project.
Project-side files (in your repo)
Section titled “Project-side files (in your repo)”.mcp.json
Section titled “.mcp.json”Location: repo root.
What it is: declares MCP servers Claude Code should connect to in this project’s sessions. JSON object with a top-level mcpServers key.
Minimal contents for a Tapestry-consuming project:
{ "mcpServers": { "loom-memory": { "type": "http", "url": "https://your-memory-host.example.com/mcp/memory/" } }}Why it exists: explicit per-project MCP wiring. If the tapestry-discipline plugin’s own MCP declaration fails to load for any reason, this file ensures the memory tools remain available.
If missing: the agent has no memory_recall/memory_write tools UNLESS the discipline plugin successfully declares them (it usually does, but defense-in-depth fails when both layers fail).
Gitignore status: typically gitignored if it contains secrets (API tokens in headers). Pure URL-only contents can be committed safely.
.claude/settings.json
Section titled “.claude/settings.json”Location: .claude/settings.json at repo root.
What it is: project-shared Claude Code settings. Critically: enables plugins for this project.
Minimal contents:
{ "enabledPlugins": { "tapestry-discipline@tapestry": true }}Why it exists: plugins are installed-once-per-machine but enabled-per-project. This file is the per-project opt-in.
If missing or empty: no plugins fire. The agent operates in stock Claude Code mode. No discipline hooks, no auto-recall, no memory MCP declared via plugin.
Gitignore status: committed (shared across team members).
.claude/settings.local.json
Section titled “.claude/settings.local.json”Location: .claude/settings.local.json at repo root.
What it is: local-only overrides per developer. Most commonly used for permissions.allow lists of WebFetch domains or MCP server enables.
Why it exists: lets individual developers add personal permissions without polluting the shared settings.
If missing: non-blocking. Defaults apply.
Gitignore status: typically gitignored.
Location: repo root.
What it is: plain-text env-var declarations. At minimum should contain LOOM_PROJECT_ID. Often also contains OTel credentials, API keys, DB URLs.
Minimal contents for Tapestry-consuming projects:
LOOM_PROJECT_ID=your-project-idWhy it exists: the LOOM_PROJECT_ID is the scope gate for the tapestry-discipline plugin’s hooks (v0.1.12+) AND the tag applied to memory writes from this project.
If missing or empty: hooks may no-op (no scope to activate against). Memory writes may be untagged or default-tagged. Cross-project memory recall becomes unfocused.
Gitignore status: ALWAYS gitignored. Never commit. Contains secrets.
.project-intelligence/<project-id>/
Section titled “.project-intelligence/<project-id>/”Location: .project-intelligence/your-project-id/ at repo root.
What it is: per-project agent configuration directory. Contains:
agent-profile.json— role, memory tag, discipline rulesproject-context.json— what this project is aboutobservatory-config.json— what events to log, what triggers candidatesworkflow-candidates/— local longitudinal state for skill candidates the agent surfacespromotion-candidates/— outbox for items the agent thinks should become durable structure
Why it exists: the discipline plugin is generic across all projects. This directory tells it what specialization to apply for THIS project (role, observability, candidate triggers).
If missing: the agent loses per-project specialization. Generic discipline still applies but role-specific behavior is gone.
Gitignore status: committed. The configs are intentional shared decisions.
CLAUDE.md
Section titled “CLAUDE.md”Location: repo root.
What it is: plain markdown auto-loaded by Claude Code at session start. Conventional content includes project description, agent role, memory hierarchy pointers, discipline rules, token discipline conventions, tone.
Why it exists: primary per-project context Claude Code auto-loads. Different from .project-intelligence/ (which is JSON config); CLAUDE.md is prose for the agent to read.
If missing: the agent has no project-specific context beyond what hooks inject. The agent might function but loses project-specific framing.
Gitignore status: committed.
scripts/architecture_snapshot.py and scripts/architecture_diff.py
Section titled “scripts/architecture_snapshot.py and scripts/architecture_diff.py”Location: scripts/ at repo root.
What it is: snapshot pipeline scripts that produce a structural snapshot of your repo and a diff against the prior baseline. For Tapestry-consuming projects, these should be thin wrappers that dispatch to the canonical implementations in the tapestry-patterns plugin.
Why it exists: the tapestry-discipline plugin’s SessionStart hook runs these to inject the architecture context into the session’s initial state. Without them, the hook silently no-ops on the snapshot piece.
If missing: SessionStart still fires (auto-recall still happens) but no architecture context is added. The agent loses structural awareness at session start.
Gitignore status: committed (they’re code).
Reference: the wrapper pattern as applied in a real consuming project.
.project-intelligence/<project-id>/workflow-candidates/
Section titled “.project-intelligence/<project-id>/workflow-candidates/”Location: .project-intelligence/<project-id>/workflow-candidates/ at repo root.
What it is: per-project longitudinal state for the Path A observer (see The observer). One JSON file per skill the observer has surfaced in any session; each file tracks cumulative sessions_seen, the most-recent status, and the prior session IDs where the skill appeared.
Why it exists: the observer runs at the end of every session, but candidates only make sense over time. This directory keeps the count across sessions so the observer can dedup and advance status (draft → observed → recurring) without re-reading every prior transcript.
If missing: the observer recreates the directory on next emission. Cumulative state from prior sessions is lost — every skill in repeated sessions emits as a new candidate every time, status never advances past draft.
Gitignore status: committed (it’s intentional cumulative state, useful as an audit trail).
docs/architecture-snapshots/ directory
Section titled “docs/architecture-snapshots/ directory”Location: docs/architecture-snapshots/ at repo root.
What it is: output directory for the architecture snapshot scripts. Contains timestamped *-snapshot.json, *-diff.json, and *-narrative.md files.
Why it exists: historical record of structural changes. Each snapshot is the input for the next diff.
If missing or empty: first snapshot has no prior baseline to diff against, so the first session produces a snapshot but no diff. Subsequent sessions work normally.
Gitignore status: typically committed (they’re auditable history). Some setups gitignore them to reduce repo size; either is defensible.
Platform-side (hosted, not in your repo)
Section titled “Platform-side (hosted, not in your repo)”The loom-memory MCP server
Section titled “The loom-memory MCP server”Location: https://your-memory-host.example.com/mcp/memory/ (hosted on Render).
What it is: HTTP-transport MCP server exposing six memory tools (memory_recall, memory_read, memory_write, memory_search, memory_list, memory_delete).
Why it exists: the canonical cross-session, cross-agent memory store. Every Tapestry-consuming project uses the SAME hosted instance.
If down: all memory operations fail. CORE DIRECTIVE 1 says the agent should HALT and report when the MCP is unavailable. In practice, sessions can still PROCEED but the operator should know they’re degraded.
Health check: curl https://your-memory-host.example.com/health returns {"status":"ok","service":"memory-mcp"}.
The tapestry-discipline plugin (cached locally per machine)
Section titled “The tapestry-discipline plugin (cached locally per machine)”Location: ~/.claude/plugins/cache/tapestry/tapestry-discipline/<version>/.
What it is: a Claude Code plugin. Contains hook scripts (hooks/run-python.mjs dispatcher + Python hook implementations under scripts/), agent files, skill files, command files, and a plugin.json that declares the loom-memory MCP.
Why it exists: the source of all discipline behavior. Installed once per machine; enabled per project.
If missing: plugin enable in .claude/settings.json resolves to nothing; no hooks fire.
Install: /plugin marketplace add Lizo-RoadTown/tapestry, then /plugin install tapestry-discipline@tapestry.
Current version: check ~/.claude/plugins/cache/tapestry/tapestry-discipline/ for the latest cached version. v0.1.13+ honors LOOM_PROJECT_ID as the scope gate; v0.1.12+ added the explicit mcpServers.loom-memory declaration.
The tapestry-patterns plugin (cached locally per machine)
Section titled “The tapestry-patterns plugin (cached locally per machine)”Location: ~/.claude/plugins/cache/tapestry/tapestry-patterns/<version>/.
What it is: the canonical patterns plugin. Contains the reusable agents and skills (documentation, deep-research-pattern, next-actions-planning, infrastructure-mapping, etc.) AND the canonical architecture-snapshot scripts that consuming-project wrappers dispatch to.
Why it exists: Pillar 1 of the MANIFESTO — “one pattern, one home, available everywhere via reference.” Skills live in the plugin, not duplicated in every repo.
If missing: consuming projects can still wrap their own architecture-snapshot scripts but lose access to the canonical agents and skills via the tapestry-patterns: namespace.
Install: /plugin marketplace add Lizo-RoadTown/tapestry, then /plugin install tapestry-patterns@tapestry.
The Path A observer (inside the tapestry-discipline plugin)
Section titled “The Path A observer (inside the tapestry-discipline plugin)”Location: ~/.claude/plugins/cache/tapestry/tapestry-discipline/<version>/scripts/observer.py.
What it is: the Stop-hook observer that parses session transcripts, counts skill invocations, dedups against .project-intelligence/<project-id>/workflow-candidates/, and POSTs candidates to the architecture-registry as evidence accumulates. See The observer.
If missing: candidates from session activity stop emitting. Manual operator POSTs become the only path into the registry.
The self-observer Render cron
Section titled “The self-observer Render cron”Location: runs as a scheduled job (every 6h). Source at services/self-observer/.
What it is: the cross-repo drift scanner. Walks registered repos via GitHub API, applies signal rules (agent / tool / skill / orphan), emits drift candidates to the architecture-registry, writes a synthesis memo to the loom-memory MCP as self_observer_synthesis_latest. See The observer.
Health check: read self_observer_synthesis_latest from the MCP. Should be within the last 6 hours. If older, check the Render dashboard for the self-observer service.
If down: Pillar-1 violations (duplicates of canonical patterns in non-canonical homes) and cross-repo drift accumulate undetected.
Environment variables
Section titled “Environment variables”LOOM_PROJECT_ID
Section titled “LOOM_PROJECT_ID”Where: .env in your project root.
What: the project identifier. Kebab-case, often suffixed -dev for projects that may spawn an -app instance.
Why: scope gate for the discipline plugin’s hooks (v0.1.12+). Tag applied to memory writes. Foreign-key into .project-intelligence/<project-id>/.
Examples: your-project-dev, team-project-staging.
OTEL_* (OTel telemetry)
Section titled “OTEL_* (OTel telemetry)”Where: .env in your project root.
What: OpenTelemetry credentials for telemetry export.
OTEL_EXPORTER_OTLP_ENDPOINT=https://<your-otlp-endpoint>/otlpOTEL_EXPORTER_OTLP_PROTOCOL=http/protobufOTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic%20<base64-token>OTEL_RESOURCE_ATTRIBUTES=service.namespace=loom,deployment.environment=devOTEL_SERVICE_NAME=loom-disciplineWhy: lets hook events flow to the same Grafana Cloud LGTM stack as other Tapestry-consuming projects, tagged with your LOOM_PROJECT_ID. Enables cross-project observability.
If missing: hooks still fire and discipline still applies. Just no telemetry export.
TAPESTRY_*_URL and LOOM_*_URL env vars
Section titled “TAPESTRY_*_URL and LOOM_*_URL env vars”Where: optional in .env, or set at deploy time.
What: override the default platform service URLs. The naming precedence is TAPESTRY_<X>_URL (Tapestry-aware deployments) → LOOM_<X>_URL (pre-Tapestry deployments) → hardcoded default.
Examples:
TAPESTRY_MEMORY_MCP_URLorLOOM_MEMORY_MCP_URL— full URL of the memory MCPTAPESTRY_ARCHITECTURE_REGISTRY_URLorLOOM_ARCHITECTURE_REGISTRY_URL— architecture-registry base URLTAPESTRY_AGENT_CONTEXT_URLorLOOM_AGENT_CONTEXT_URL— agent-context base URL
Why: lets consuming projects point at alternate deployments (staging, alternate region, future Tapestry-hosted services) without code changes.
If unset: the deployment’s configured default hosts apply.
Marketplaces
Section titled “Marketplaces”tapestry (canonical)
Section titled “tapestry (canonical)”Source: https://github.com/Lizo-RoadTown/tapestry. The marketplace manifest lives at the repo root in .claude-plugin/marketplace.json; plugins live under integrations/claude-code/.
Contents: the tapestry-discipline plugin and the tapestry-patterns plugin.
Add to Claude Code: /plugin marketplace add Lizo-RoadTown/tapestry.
File-existence audit at session start
Section titled “File-existence audit at session start”To audit a project for discipline-stack completeness, run from the repo root:
echo "=== Discipline stack audit ==="test -f .mcp.json && echo "OK: .mcp.json" || echo "MISSING: .mcp.json"test -f .claude/settings.json && echo "OK: .claude/settings.json" || echo "MISSING: .claude/settings.json"test -f .env && echo "OK: .env" || echo "MISSING: .env"test -d .project-intelligence && echo "OK: .project-intelligence/" || echo "MISSING: .project-intelligence/"test -f CLAUDE.md && echo "OK: CLAUDE.md" || echo "MISSING: CLAUDE.md"test -f scripts/architecture_snapshot.py && echo "OK: snapshot script" || echo "MISSING: snapshot script"echo "=== LOOM_PROJECT_ID ==="grep LOOM_PROJECT_ID .env 2>/dev/null || echo "MISSING: LOOM_PROJECT_ID in .env"echo "=== Enabled plugins ==="cat .claude/settings.json 2>/dev/null | grep -iE "tapestry-discipline|loom-discipline" || echo "MISSING: tapestry-discipline (or transitional loom-discipline) in settings.json"If any line shows MISSING, see Recover from common failures for the fix.