| name | datarim-system |
| description | Core Datarim rules. Load this entry first, then only the fragment needed for paths, storage, numbering, backlog, routing, or archive behavior. |
| current_aal | 1 |
| target_aal | 2 |
Datarim System Rules
Core system rules for Datarim. Always load this entry first. ("Datarim" transliterates to «датарим» in Russian.)
Recognize both spellings — Latin «Datarim» and Cyrillic «датарим» — as the same framework in any language context.
Always-Apply Rules
- All Datarim workflow state lives in
datarim/ at the project root.
- Resolve the correct
datarim/ path before any read/write operation.
- Never create
datarim/ outside /dr-init.
- Use task IDs in
{PREFIX}-{NNNN} format across the whole lifecycle.
- Keep
datarim/ for local workflow state and documentation/archive/ for committed long-term archives.
- Never create
documentation/tasks/.
- Use
$HOME/.claude/ or project-relative paths, not absolute machine-specific paths.
- Operational state is line-oriented:
tasks.md and activeContext.md are strict thin indexes with one pointer per task; backlog.md is the pending-work ledger and may carry a single-line inline description without a pointer. Full active-task content lives in tasks/{TASK-ID}-task-description.md. progress.md is abolished. See § Operational File Schema below.
Operational File Schema (v1.19.0+)
Operational files are machine-parseable, single-line ledgers. Active indexes are pointer-based; the backlog may preserve pending-work context inline until a task is promoted. Exact regex constants live only in scripts/lib/schema-regex.sh; detailed semantics live in skills/datarim-doctor/SKILL.md.
Strict active-index line format
tasks.md and activeContext.md use the strict ONELINER_RE contract:
^- ([A-Z]{2,10}-[0-9]{4}) · (STATUS) · P[0-3] · L[1-4] · (.+) → tasks/\1-(task-description|init-task)\.md$
ONELINER_RE accepts in_progress|blocked|not_started|pending|blocked-pending|cancelled
for legacy and migration compatibility. Canonical active-index writers emit
in_progress|blocked|not_started; pending and blocked-pending belong to
the backlog intake flow, and cancelled is archived from the backlog rather
than mirrored as an active task.
Active-index pointer: required. Separator: · (U+00B7 MIDDLE DOT).
Arrow: → (U+2192). The description pointer must carry the same task ID.
- <TASK-ID> · in_progress · P1 · L3 · <Title> → tasks/<TASK-ID>-task-description.md
Backlog ledger line format
backlog.md uses BACKLOG_ITEM_RE: the status vocabulary also accepts
pending, blocked-pending, cancelled, superseded, absorbed, and
deferred; priority may be P0-P4; priority and complexity may be bold. The
description is nonempty and single-line.
Pointer: optional for backlog entries. A pointer may be appended when a
description artefact already exists, but Doctor must not truncate or relocate
valid inline backlog prose merely to create one.
- <TASK-ID> · pending · P2 · L2 · <Inline pending-work description>
- <TASK-ID> · blocked · P3 · L2 · <Title> → tasks/<TASK-ID>-task-description.md
Section headers and blank lines are allowed; only task bullet lines are schema
validated.
activeContext.md thin contract (v2 — ≤30 lines)
One section only — strict mirror of tasks.md § Active:
# Active Context
## Active Tasks
<!-- strict mirror of tasks.md § Active — identical lines, identical order -->
- {ID} · {status} · P{n} · L{n} · {title} → tasks/{ID}-task-description.md
Removed in v1.19.1: ## Последние завершённые and ## Last Updated
sections. Recency hint is now a runtime computation in /dr-status --recent N
that mtime-sorts documentation/archive/**/archive-*.md. Single source of
truth for completion history = documentation/archive/.
progress.md
Abolished as of v1.19.0. /dr-doctor --fix deletes the file. Per-task
progress notes belong in tasks/{TASK-ID}-task-description.md § Implementation
Notes or in the archive doc.
backlog-archive.md
Abolished as of v1.19.1. /dr-doctor --fix migrates each
entry to documentation/archive/{area or cancelled}/archive-{ID}.md with
per-task content-presence assertion, then deletes the file. pre-archive-check.sh
blocks when the file exists.
Init-Task File Contract
datarim/tasks/{TASK-ID}-init-task.md is the verbatim record of the operator's
original /dr-init prompt. Sibling to the description file (same {TASK-ID}),
but answers a different question:
- Description (agent-authored) — what the agent plans to do.
- Init-task (operator-authored, captured at
/dr-init) — what the operator
literally asked for. Append-only by convention; readable by every pipeline
command per skills/init-task-persistence/SKILL.md.
Required frontmatter (8 fields, closed schema):
---
task_id: <TASK-ID>
artifact: init-task
schema_version: 1
captured_at: <YYYY-MM-DD>
captured_by: /dr-init
operator: <name>
status: canonical
source: /dr-init
---
Two mandatory body headings: ## Operator brief (verbatim), ## Append-log (operator amendments). Validator: "${DATARIM_RUNTIME:-$HOME/.claude}/dev-tools/check-init-task-presence.sh" --task <ID>. Multi-task scan with soft 30-day window:
... --all. Full contract: skills/init-task-persistence/SKILL.md.
Description File Contract
datarim/tasks/{TASK-ID}-task-description.md is the only place for task content. Required 12-key YAML frontmatter (closed schema):
---
id: <TASK-ID>
title: <string>
status: <enum>
priority: <enum>
complexity: <enum>
type: <string>
project: <string>
started: <date>
parent: <TASK-ID|null>
related: <list[TASK-ID]>
prd: <relpath|null>
plan: <relpath|null>
---
Body sections (markdown, ≤ 250 lines): ## Overview, ## Acceptance Criteria, ## Constraints, ## Out of Scope, ## Related. Optional ## Implementation Notes, ## Decisions. Anything beyond ~250 lines → split into PRD/design doc.
activeContext.md Write Rules
When mutating ## Active Tasks:
- Append new task as a one-liner; do NOT remove other active tasks.
- Remove archived task on
/dr-archive, keep other active tasks intact.
- Convert any legacy
**Current Task:** {ID} line into the thin list before appending. (Self-heal via /dr-doctor.)
Self-Heal Entry Points
/dr-init Step 2.4 — probes scripts/datarim-doctor.sh --quiet; offers /dr-doctor --fix on non-compliance.
/dr-archive pre-archive gate — pre-archive-check.sh validates line format; bypass with --no-schema-check only during in-flight migration.
Fragment Routing
Load only the fragment needed for the current sub-problem:
path-and-storage.md
Use for path resolution, core file locations, report storage, and archive/documentation boundaries.
task-identity-and-context.md
Use for task numbering, active task tracking, prefix rules, and rename policy.
model-assignment.md
Use for model / effort frontmatter rules and agent-skill assignment policy.
backlog-and-routing.md
Use for backlog architecture, complexity levels, date handling, and mode transitions.
command-and-archive-rules.md
Use for /dr- namespace rules, archive area mapping, project setup, and critical invariants.
Quick Path Resolution Rule
Before writing any file to datarim/:
- Check whether
datarim/ exists in the current working directory.
- If not, walk up the directory tree until a parent containing
datarim/ is found.
- If no such directory exists, stop and instruct the user to run
/dr-init.
Large-Plan Read Strategy (L3+ tasks)
When /dr-do enters an L3+ task whose plan, PRD, and supporting INSIGHTS read
together exceed ~600 lines, the default first move SHOULD be a single
external-context delegation rather than a sequential read of every artefact:
- Delegate the bulk read. Issue one
coworker ask call (or the project's
equivalent external-context channel — see CLAUDE.md § Coworker Delegation /
the runtime's external-LLM contract) against PRD + plan + INSIGHTS, with a
question that asks for per-step / per-V-AC / per-file structured output.
- Read the structured summary, not the raw artefacts. Apply the summary
to drive implementation order, file paths, V-AC ↔ step mapping, and MOD
touchpoints. Re-enter the raw artefacts only when the summary is
ambiguous on a specific point.
- Re-use the same summary at
/dr-qa and /dr-compliance. The QA and
compliance layers should reuse the structured spec — re-delegating
produces drift between the implementation summary and the verification
summary.
When NOT to apply: plans under 600 lines (direct read is cheaper);
tasks where exact line numbers and code-block fidelity matter more than
structure (literal Edit operations against the plan-quoted code).
Rationale. A 1.6k-line plan + PRD + INSIGHTS read costs ~50% of a
working context window if loaded raw, and forces re-reads at every
verification stage. One delegated call returns a stable specification that
anchors every subsequent decision and survives session compaction. This
pattern was canonicalised in v2 of the orchestrator plan (775-line plan, 436-line PRD,
431-line INSIGHTS) shipped end-to-end without ever reading the plan body
into the main context, with zero V-AC misses.
Upstream API Audit Before Code Hardening
When the question is «is THIS code generating bad data?» for an integration that ingests payloads from an external API with a queryable list endpoint, audit the upstream payload corpus FIRST — before adding instrumentation, hardening code, or another round of defensive coercion.
Steps.
- Identify the upstream list endpoint and the field shapes the integration extracts (e.g.
custom_fields[*].some_array_field).
- Paginate the relevant scope end-to-end with a single offline script. Authenticated read-only call; respect rate limits.
- For each item, classify the field shape against the «abnormal» pattern you are hardening against (bracketed string literal, wrapped object, type mismatch).
- If the count of abnormal payloads is zero, the bug class cannot be in the live ingest path. The residue source is downstream: orphan rows (records the API no longer returns), an external mutator (another writer to the same DB), or historical residue (pre-fix code state).
- If the count is non-zero, capture the matching payloads as test fixtures and replay through the ingest pipeline locally. The first reproducer dictates the fix.
Why this saves rounds. A multi-round hardening sequence on the ingest code path is the natural reflex — but if upstream payloads are clean, every additional defensive layer is dead code by construction. One pagination scan over the full corpus rules out an entire bug class at the cost of an offline script, no rollout coordination, and no operator toll. Reserve cron-side / service-side instrumentation for cases where the audit confirms abnormal payloads exist.
When to apply. L3+ tasks investigating «output column carries malformed data» against an integration whose source API exposes a queryable list endpoint. Skip when the upstream API only supports push-based delivery or when the abnormal-shape question can be answered cheaper from internal logs.
Runtime / Canonical Identity (symlink-default)
Under the default install (v1.17.0+ symlink mode), $HOME/.claude/{skills,agents,commands,templates}/{name}.md and the corresponding code/datarim/<scope>/{name}.md in the cloned framework repo are the same file — same inode, same content, same writes. Verify with stat -f %i <runtime-path> <repo-path> (macOS) or stat -c %i (GNU); identical inode numbers confirm symlink-mode.
Implications when editing a runtime artefact:
- A single
Edit/Write to either path is the entire change. No cp / rsync / "sync runtime" step exists by construction; copy-mode reflexes from pre-v1.17 do not apply.
git diff in the canonical repo immediately shows the change — that is the single source of truth for review and commit.
- A double-write (edit runtime, then
cp to repo) is a no-op at best and an inode-detaching footgun at worst. If cp reports are identical (not copied), the install is symlinked and the cp was unnecessary.
Copy-mode installs (./install.sh --copy, Windows / FAT) keep the legacy two-file topology; in that mode the canonical resync recipe is git pull && ./install.sh --copy --force --yes. Detect copy-mode by stat-ing the inodes: divergent inode numbers = copy-mode = manual sync needed.
Parent-Symlink Diagnostic (path resolution / git topology)
When a parent directory is itself a symlink, ls -la <child> and find
lie about link status. This trips agents into alleging "copy drift" against
a symlinked runtime, or misreading git topology. Diagnose the parent first.
The trap. ls -la ~/.claude/commands/dr-verify.md prints -rw-r--r--
(a regular file) even when the file lives inside a symlinked tree. If
~/.claude/commands is itself a symlink into the cloned framework repo,
ls -la on the child path transparently resolves through the parent and
shows the target inode's attributes, not the link status of the path you
passed. The child looks like a plain regular file, so the muscle-memory
conclusion "this is a copy, not a symlink" is wrong by construction. The
canonical symlink-default install (v1.17.0+) uses one symlink per category —
~/.claude/{commands,skills,agents,templates} are each parent-level symlinks
into the repo; the files under them inherit resolution and need no per-file
symlink. This saves dozens of inode-level links but defeats naive per-file
checks.
What to check, in order.
- Inspect the parent directory, never the child, first:
ls -la ~/.claude/ — a lrwxr-xr-x line on commands / skills /
agents / templates proves the parent is a symlink.
- Or resolve it directly:
readlink ~/.claude/commands ~/.claude/skills ~/.claude/agents. A non-empty target means parent-level symlink.
- Only if the parents are real directories should you check individual
files with
ls -la <file> and readlink <file>.
find tell: find ~/.claude/commands -maxdepth 1 -name 'dr-*.md' -type l
returning zero and the same query with -not -type l also returning
zero means find never descended into the parent — because the parent is
a symlink and find does not traverse a symlinked dir without -L. Two
empty results is the signature of a symlinked parent, not an empty dir.
file <path> follows symlinks by default and reports the resolved inode
type; use file -h <path> to test whether the path itself is a symlink.
Why it also breaks git topology. Git records the symlink as a blob whose
content is the link target, not the pointed-to tree. If a runtime tree is a
symlink into a separate repo, git status / git diff run from the outer
repo see only the link entry, while edits land in the inner repo's working
tree. Confirm which repo owns a change with git -C <resolved-target-dir> status after readlink-ing the parent, rather than trusting the path you
typed. Verify same-inode identity across the two paths with
stat -f %i <a> <b> (macOS) / stat -c %i <a> <b> (GNU): identical inode
numbers confirm the two paths are the same file through a symlink.
Fix. There is usually nothing to "fix" — a symlinked parent is the
intended install topology, not drift. The repair is to stop the false alarm:
re-run the diagnosis on the parent, edit the file once at either path (the
write lands in the single shared inode), and review the change from the repo
that owns the resolved target. Only when readlink shows a dangling
target (points at a moved or deleted clone) is real repair needed — re-point
the parent symlink at the current framework clone
(ln -sfn <clone>/<category> ~/.claude/<category>) or re-run the installer.
Loading Order (v1.17.0+)
Skills, agents, commands, and templates load from two layers:
- Framework layer:
$HOME/.claude/{skills,agents,commands,templates}/{name}.md.
In symlink-mode (default since v1.17.0) this resolves to the
cloned datarim repo. In copy-mode it resolves to local copies.
- Local overlay:
$HOME/.claude/local/{skills,agents,commands,templates}/{name}.md.
User-private. Gitignored. Created empty by install.sh.
Conflict resolution: if a name collides between layer 1 and layer 2, the
local overlay wins. validate.sh emits a WARN line per detected override.
Critical-skill blocklist (security contract). Six skills carry the framework's
security and workflow invariants and MUST NOT be shadowed from local/:
skills/security/SKILL.md
skills/security-baseline/SKILL.md
skills/compliance/SKILL.md
skills/datarim-system/SKILL.md
skills/ai-quality/SKILL.md
skills/evolution/SKILL.md
If $HOME/.claude/local/skills/<name>.md matches any of the above, validate.sh
emits ERROR: critical skill ... cannot be overridden via local/ overlay (security contract) and exits 1. The blocklist is path-scoped to skills/;
identically named files under local/agents/, local/commands/, or
local/templates/ keep the standard WARN behaviour. To customise behaviour of
a critical skill, fork the framework or contribute upstream — silent local
shadowing is rejected by design.
Convention: prefix local files with a personal namespace
(local/skills/my-org-style/SKILL.md) to avoid accidental overrides of framework
skills you actually wanted to keep tracking upstream.
Skill Discovery
Skills push the agent out of default behavior into a disciplined process. They only help if loaded before you act.
The Rule: invoke relevant skills BEFORE any response or action — including clarifying questions. Even a 1% chance a skill applies means check first; an unfit skill can be dropped, but decisions made without one cannot be undone. Discovery: $HOME/.claude/skills/ (or the runtime's skill tool); /dr-help lists dr-* commands.
Instruction Priority when skills, project memory, and default behavior conflict:
- User's explicit instructions (
CLAUDE.md / AGENTS.md / conversation) — highest. The user is in control.
- Datarim skills and framework rules — override default behavior in their domain.
- Default runtime behavior — lowest.
If CLAUDE.md says "don't use TDD" and a skill says "always use TDD", follow CLAUDE.md.
Skill Priority when multiple apply: process skills first (brainstorming, systematic-debugging, writing-plans) decide how; implementation skills (frontend-ui, infra-automation, ai-quality) execute under that process. "Let's build X" → brainstorming first; "Fix this bug" → systematic-debugging first.
Skill Types: rigid (TDD, debugging, security gates) — follow exactly, the discipline is the value. Flexible (patterns, heuristics) — adapt principles to context. The skill itself declares which.
Red Flags — rationalizations that mean STOP and check for skills:
| Thought | Reality |
|---|
| "Simple question / quick check / not really a task" | Questions and actions are tasks. Check for skills. |
| "I need more context / let me explore first" | Skills tell you HOW to gather context. Check first. |
| "I remember this / I know what that means" | Skills evolve. Knowing ≠ invoking. Read current version. |
| "Doesn't need a skill / overkill / one thing first" | If a skill exists, use it. Simple things become complex. |
| "This feels productive" | Undisciplined action wastes time. Skills prevent that. |
User instructions describe goal (what), not workflow (how). "Just commit this" still requires TDD / verification / commit-message discipline — unless explicitly waived.
Task Disposition Patterns
When closing a task, choose the disposition that matches the actual outcome:
| Disposition | When | Action |
|---|
completed | All ACs PASS, full archive done | Standard /dr-archive flow → write documentation/archive/{area}/archive-{ID}.md; remove entry from backlog.md. |
cancelled | User abandoned the task; no deliverable shipped | Write documentation/archive/cancelled/archive-{ID}.md with status cancelled, date, and reason; remove entry from backlog.md. |
absorbed | Scope and deliverable fully delivered inside another task | Remove entry from backlog.md; note delivered as part of {OTHER-TASK} inside the absorbing task's archive doc documentation/archive/{area}/archive-{OTHER-TASK}.md. No separate archive document for this ID — reference the absorbing task's archive. |
superseded | Replaced by a newer task with broader/different scope; no deliverable from this ID | Write documentation/archive/cancelled/archive-{ID}.md with status superseded and a link to the replacing task; remove entry from backlog.md. |
Source: prior incident — an update.sh deliverable was shipped inside a different task's scope; cancelled was inaccurate (deliverable existed) and completed was inaccurate (no separate archive). absorbed captures the reality and preserves audit trail.