Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .claude/agents/archivist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
name: archivist
description: Grooms ONE architecture doc to ARCHITECTURE_COMMON.md - applies the belonging test (five classes, nothing else; unrelated prose DELETED and listed), the mood test (modal sentences become REVIEW.md proposals, past-tense/dated passages archive to /history, plans move to ledgers), and the 300-line split (whole sections into ARCHITECTURE_<CONCERN>.md companions, concerns clustered by the [arch] citation census). Anchored sections are load-bearing: never deleted, moved only with every citation - [arch(at=...)] annotations, sec.N cites in the folder's rule docs - updated in the same change, proven by LINT026. Meaning-preserving; never invents content; semantic forks go to a NEEDS RULING queue. Edits the doc, its companions, /history, and citing annotations; REVIEW.md changes are proposed, never applied. Run the dragon on the result afterward.
model: opus
tools: Read, Grep, Glob, Edit, Write, Bash
---

You are the archivist. You groom one architecture doc into contract shape. Read first:
`ARCHITECTURE_COMMON.md` (repo root - the law), `skills/internal/doc_archiving.md` (the
/history process), the folder's `REVIEW*.md` files (you must know which sections their rules
cite), then the whole target doc. When the folder's code carries `[arch(at=...)]` citations,
run the census before deciding anything (`git grep` for the citations, or the MCP
`arch_sites` tool when available): cited sections are load-bearing.

## The verdicts, per section or passage

- **KEEP** - one of the five classes (file charters, mechanisms, definitions, inventories,
the exception ledger), present tense, earning its place.
- **DELETE** - prose that is none of the five classes, or that changes nothing about what a
reader writes or concludes. Delete outright; the report lists every cut, condensed to its
point, so nothing drowns silently. An ANCHORED or rule-cited section is never DELETE - when
its content seems dead, queue it instead.
- **ARCHIVE** - past-tense or dated narrative of what happened. Move verbatim to
`history/<area>/` per the doc_archiving process, archive-log line included.
- **ROUTE** - a modal sentence (must/never/"is a defect") binding a diff. Propose it for the
folder's `REVIEW.md` in ban-or-duty form per `REVIEW_COMMON.md`; delete it from the arch
doc only in the same change that your report proposes the landing - never silently.
- **LEDGER** - a plan, promise, or phase. Move to the folder's follow-up ledger.

## The split

A doc past 300 lines splits at section boundaries into `ARCHITECTURE_<CONCERN>.md`
companions beside it. Concerns cluster by who cites what - the citation census first,
content affinity where no citations exist. Sections move WHOLE: heading, `{#anchor}`,
body. In the same change, update every citation of a moved section: `[arch(at=...)]`
annotations in code (the path changes to the companion), `sec.N` cites in the folder's
rule docs, and path-qualified mentions the grep finds. Companion files open with one line
naming the parent doc; the parent keeps a one-line pointer per companion. Never renumber a
surviving section; a companion keeps its sections' numbers.

## What you never do

- Never delete or strip an anchor. Never delete an anchored or rule-cited section - queue
the doubt.
- Never invent content, reword a kept statement beyond the plain-English/no-clutter rules,
or change what any statement claims. When a claim looks stale against the code, verify;
fix it only when the code proves the correction, else queue it.
- Never edit a `REVIEW*.md` - route as proposals in the report.
- Never leave a citation - annotation, sec-cite, or link - pointing at a section you moved.
Prove it: run the lint's LINT026 pass over the folder and grep the old paths; both go in
the report.

## Report

1. Counts: sections KEEP / DELETE / ARCHIVE / ROUTE / LEDGER, lines before -> after
(per file after a split).
2. The cut list - every DELETE, condensed to its point.
3. The split map - which sections went to which companion, and every citation updated.
4. ROUTE proposals - exact REVIEW.md text, ban-or-duty form.
5. `NEEDS RULING:` - anchored-but-dead sections, stale claims code did not settle,
semantic forks. "none" when empty.
6. Proof lines: the LINT026/lint run result and the old-path grep result.
6 changes: 4 additions & 2 deletions .claude/agents/harvester.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ other filing unnecessary. Only a comment no name can carry goes on to the rest.
architecture doc, as a present-tense statement per `ARCHITECTURE_COMMON.md`, naming the
section it joins. Delete the comment.
- **KEEP** - a constraint true only at this code site, which filing to the architecture doc
would bury. Compress to one line in place. A comment already in the hygiene skill's kept
set (doc comments, license headers, sanctioned markers) is KEEP verbatim - no compression.
would bury. Compress to one line in place, spelled `//!` - a contract comment, legal on
any visibility (a private `//!` caps at 3 lines under STYLE015). A comment already in the
hygiene skill's kept set (doc comments, license headers, sanctioned markers) is KEEP
verbatim - no compression.
- **DROP** - it narrates, restates the code, or records history. Delete it.
- **TODO** - unfinished work. Propose the follow-up ledger line; delete the comment.

Expand Down
4 changes: 2 additions & 2 deletions .claude/hooks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ work when the das binary is down.
There is deliberately no write-time comment hook: comments are working
scaffolding - write them freely during a PR. The gate is `make_pr`'s comment
drain: the formatter strips them per the folder's `.lint_config` policy, and a
non-empty strip goes through the `rescue-bot` agent (report-only ledger; the
session rules on every rescue). Policy: `skills/comment_style_hygiene.md`;
non-empty strip goes through the `harvester` agent (proposal ledger; the
session rules on every entry). Policy: `skills/comment_style_hygiene.md`;
mechanics: `skills/internal/make_pr.md`.

## monitor_guard.jq - PreToolUse, `Monitor|Bash`
Expand Down
21 changes: 18 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,29 @@ Three document types split one grammar, each with a repo-root contract:
- **`/history`** - past tense: what happened. Nothing current cites it.

An implementation folder - `daslib/`, a module's `daslib/` or engine folder - holds no `.md`
besides `REVIEW*.md`, `ARCHITECTURE.md`, and `LAWS.md` (lint-enforced: `.lint_config`
besides `REVIEW*.md`, `ARCHITECTURE*.md`, and `LAWS.md` (lint-enforced: `.lint_config`
`rule_docs_only`). Ledgers and plans live at the module root or in `plans/` (repo root). None
of these documents installs - the SDK bundle gate bans them; `REVIEW_COMMON.md` and
`ARCHITECTURE_COMMON.md` at the install root are the two vendoring exceptions.

The mood test routes misplaced text: must/never binding a diff -> REVIEW.md; present-tense
fact -> ARCHITECTURE.md; dated or past-tense -> /history.

**Before editing a function annotated `[arch(at="<doc>.md#<anchor>")]`, read the section it
cites.** MCP `arch_of` returns each of a file's citations with its section text; `arch_sites`
returns a document's anchors with the code citing them, dead anchors and dangling citations
included. Citation spelling, path resolution, and failure reasons: `skills/mcp_tools.md`.

**An architecture-doc heading that code cites carries the `{#anchor}` its citation names.**
LINT026 fails a citation naming no such file or anchor, and in a folder whose `.lint_config`
sets `[docs] enforce_arch = true`, an anchor no `[arch]` cites.

**A `REVIEW*.md` or `ARCHITECTURE*.md` past 300 lines, in a folder whose `.lint_config` sets
`[docs] rule_docs_only = true` or `[docs] enforce_arch = true`, splits into companions** -
`ARCHITECTURE_<CONCERN>.md` for an architecture doc, a `REVIEW_<KIND>.md` the parent
checklist's opening routes to for a checklist. LINT027 is the gate; the `archivist` agent
does the architecture-doc splits.

## GitHub Operations

Use GitHub MCP tools (`mcp__github__*`) for all GitHub operations (PRs, issues, reads) - they avoid shell escaping entirely. Fallback when unavailable: `gh` CLI with `--body-file` for any text containing backticks (shell escape characters in every supported shell).
Expand Down Expand Up @@ -69,7 +84,7 @@ Task-specific instructions are split into skill files under `skills/`. You MUST
|---|---|
| `skills/project_overview.md` | First significant task - design philosophy, three execution tiers, macros-as-design-lens |
| `skills/internal/build_and_debug.md` | Build flags, AOT build commands, exit-code/crash diagnosis, `options log_infer_passes` |
| `skills/mcp_tools.md` | Full MCP tool table + live-API reference |
| `skills/mcp_tools.md` | Full MCP tool table + live-API reference; writing or following an `[arch(at=...)]` citation |
| `skills/das_formatting.md` | Creating or modifying any `.das` file |
| `skills/comment_style_hygiene.md` | Writing or reviewing comments, names, or local code shape in ANY language |
| `skills/writing_tests.md` | Writing or editing any dastest test |
Expand Down Expand Up @@ -271,7 +286,7 @@ For path/filename ops use `fio` helpers (`base_name`/`dir_name`/`path_join`/...)

**Complexity/length lint (STYLE037/STYLE038): new code meets both limits from the start.** On a hit in existing code, the suppress-vs-split resolution policy is `skills/style_lint.md` - never force a split on an honest shape.

**Comment hygiene, all languages: `skills/comment_style_hygiene.md` is the rulebook.** For `.das` in a folder whose `.lint_config` arms `force_clean_comments` the headline is that no comment outside the skill's kept set survives to a commit - scaffolding is welcome while you work, and the PR gate drains it (`skills/internal/make_pr.md`, the Comment drain row); elsewhere the kept set still holds and every other `.das` comment answers to the skill's deletion test. For C/C++ it is no NEW comments. The kept sets, teaching-code boundary, naming and code-shape rules all live in the skill; the `style-hygiene-auditor` agent applies them to every PR's new code (mandatory run in `skills/internal/make_pr.md`, findings persuade rather than block).
**Comment hygiene, all languages: `skills/comment_style_hygiene.md` is the rulebook.** No folder arms formatter stripping any more: scaffolding is welcome while you work, and the PR gate HARVESTS the diff's added comments (`skills/internal/make_pr.md`, the Comment harvest row) - renames first, rules and facts into the folder's documents, site-local keepers as `//!` contract one-liners; every surviving `.das` comment answers to the skill's deletion test. For C/C++ it is no NEW comments. The kept sets, teaching-code boundary, naming and code-shape rules all live in the skill; the `style-hygiene-auditor` agent applies them to every PR's new code (mandatory run in `skills/internal/make_pr.md`, findings persuade rather than block).

## Key Directories

Expand Down
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2072,8 +2072,10 @@ install(DIRECTORY ${PROJECT_SOURCE_DIR}/utils/find-dupe/tests/
FILES_MATCHING PATTERN "*.das"
)

# Install utils/common (git-aware staleness signature used by
# utils/mcp/tools/cpp_common for source-search staleness tracking).
# Install utils/common. The GLOB covers every shared module, which is what keeps the shipped MCP
# server startable: it runs interpreted with no -project, and its require graph reaches
# utils/common/arch_citations.das (via utils/mcp/tools/arch_common) and
# utils/common/git_signature.das (via utils/mcp/tools/cpp_common).
file(GLOB DAS_UTILS_COMMON_FILES ${PROJECT_SOURCE_DIR}/utils/common/*.das)
install(FILES ${DAS_UTILS_COMMON_FILES} DESTINATION utils/common)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/utils/common/tests/
Expand Down
5 changes: 5 additions & 0 deletions LAWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ compacted, or cited as rules.
| 2026-08-27 | .claude/agents/harvester.md (RENAME verdict) | "what the previous resque-boat agent did for comments - the most interesting part - is suggest renames. like 'this comment is rename in disguise'. i don't want to loose that at all. its important" - RENAME added to the harvester's verdicts; comment stays until the rename lands |
| 2026-08-27 | .claude/agents/harvester.md (RENAME precedence) | "rename should be first option, before any rescue attempts. it is the strongest." - RENAME tested before RULE/FACT/KEEP/DROP/TODO; only a comment no name can carry goes on to filing |
| 2026-08-27 | CLAUDE.md (document system), CMakeLists.txt (install gate), ci/smoke_test_bundle.sh, daslib/.lint_config + utils/lint | "no random .md next to shipped code ... REVIEW.md and REVIEW.das go there, if they exist. so does ARCHITECTURE.md ... but there should be no other .md there whatsoever. lint should catch mechanically ... and related CMAKE install thing is to not install .md unless explicitly listed" + "LAWS.md can stay in the folder just like REVIEW.md, but should never ever be installed as well" - rule_docs_only lint tag; install manifest gate + bundle smoke test ban ARCHITECTURE.md/LAWS.md/ledgers; ARCHITECTURE_COMMON.md ships beside REVIEW_COMMON.md |
| 2026-08-27 | src/builtin/module_builtin_runtime.cpp, utils/lint (LINT026), utils/common/arch_citations.das, utils/mcp arch tools | the [arch] system: "annotation in the builtin, on C++ side, which does nothing. but lint does all the work" + reverse direction "if enabled - it should sweep .md and if there are anchors which can't be found in the code - same lint error" + on forward-always/reverse-opt-in as shipped: "i like whats shipped." |
| 2026-08-27 | daslib/style_lint.das (STYLE015), skills/comment_style_hygiene.md, .claude/agents/harvester.md | "//! - lint will flag on non-public functions. do we need 3rd type of comments?" -> recommendation reuse //!; ruling: "lets keep //! on non-public" - private //! is a contract comment, 3-line cap like public docs; harvester KEEP emits //! |
| 2026-08-27 | .claude/agents/archivist.md (new), utils/lint (LINT027 line gate) | ARCHITECTURE.md cleanup: "1. size - needs split by sections past 300 lines (u pick the limit...) 2. some are bunch of unrelated prose. that stuff must just go. so its an extra agent for cleanup" + "we do both this PR. i'd like to not drop anchors" - archivist agent (belonging test deletes unrelated prose, census-driven splits, anchors never dropped); 300-line lint gate on rule docs in tagged folders; both arch docs groomed in this PR |
| 2026-08-27 | skills/internal/make_pr.md | "should we update make_pr skill?" - the comment-drain row becomes the diff-scoped harvest row (the ruled harvest regime, trial passed on dasllama_image.das); rescue-bot references retired from the flow; the format row states no folder strips comments; the tree-frozen-during-preflight rule lands from this session's lib/-hiding incident |
| 2026-08-27 | .claude/agents/ (rescue-bot, rescue-sweep-bot -> history/agents/), strip-advisory strings, .claude/hooks/README.md | "yes, lets retire both. they go to /history/agents i guess. this is evolution" - both rescue bots archived; the dormant strip advisory names the harvester as successor |
4 changes: 3 additions & 1 deletion ci/make_cpp_mcp_bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ mkdir -p "$OUT/bin" "$OUT/utils/mcp/tools" "$OUT/utils/common"
cp "$BIN" "$OUT/bin/"
cp utils/mcp/*.das "$OUT/utils/mcp/"
cp utils/mcp/tools/*.das "$OUT/utils/mcp/tools/"
cp utils/common/git_signature.das "$OUT/utils/common/"
# every shared module, not just the ones cpp_main reaches: the whole tools/ directory is copied
# above, and a tool whose require target is missing from the bundle is a trap for the next reader
cp utils/common/*.das "$OUT/utils/common/"
cp -r daslib "$OUT/daslib"
# ast-grep rule files: the outline / cpp_* tools load these at runtime via
# get_das_root() (tools/outline.das, tools/cpp_common.das), so the bundle needs
Expand Down
Loading
Loading