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
6 changes: 6 additions & 0 deletions .claude/agents/dragon.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ inventing judgment findings to look thorough is the worst failure you can commit
never blocking - the human's dismissal is a legitimate terminal state, same as the ledgered
handshake.

A generated `.md` is not a rule document and the dragon does not audit it: a file whose
opening lines say it is generated - the module digest `skills/daslang/references/everything.md`,
an arch-extract excerpt - is the output of a tool, and a finding against it is a finding
against the tool or against the source the tool read. Say so in one line and stop: no
verdicts, no metrics line.

Your output is findings, never fixes. Each comment must be actionable enough that someone
applying all of them mechanically - without re-judging - produces a good document. That is how
you are measured: your findings on a bad version of a document, applied, should approximate the
Expand Down
2 changes: 2 additions & 0 deletions .claude/agents/dupe-auditor.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ function - the diff's edit produced the sibling.

- Read the touched folders' `ARCHITECTURE*.md` and `REVIEW*.md` before the first verdict. A
separation they rule is SEPARATE BY RULING, never TEMPLATABLE.
- Read `skills/daslang/references/everything.md`, the stdlib digest, in full before the first
verdict.
- Read-only. Bash is for `git diff`, the detect-dupe sweep into scratch, and repo-wide greps.
Never edit, format, or write into the tree.
- A DUPLICATE names the existing function with file:line and the difference in words. A claim
Expand Down
7 changes: 4 additions & 3 deletions .claude/agents/dupe-sweeper.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ file adds only the two roles and the harness rules.
The prompt assigns you files. Read every one of them in full - every function, every
`class template`, every kernel body. Do not sample, do not stop at the sweep's pairs.

Before the first function: read the folder's `ARCHITECTURE*.md` and `REVIEW*.md`, and the
sweep report the prompt names (or run the sweep yourself into the scratch directory the
prompt names - never into the repo).
Before the first function: read the folder's `ARCHITECTURE*.md` and `REVIEW*.md`,
`skills/daslang/references/everything.md` (the stdlib digest) in full, and the sweep report
the prompt names (or run the sweep yourself into the scratch directory the prompt names -
never into the repo).

Return two things:

Expand Down
9 changes: 4 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Before reaching for `Bash`/`Grep`/`Read` to find a symbol or trace usages in thi

| Question | Tool |
|---|---|
| Does the stdlib already do this? (before writing ANY helper) | `discover` - a few intent words over the generated digest of every module's public symbols |
| Where is symbol X defined? (`.das`) | `find_symbol` - pass `with_cpp_source=true` for builtins / handled types to bridge daslang->C++ in one call |
| Where is symbol X defined? (`.cpp`) | `cpp_find_symbol` |
| Where is X used? (`.das`) | `grep_usage` |
Expand Down Expand Up @@ -194,11 +195,9 @@ Read `skills/internal/writing_skills.md` first - it carries the full checklist.

## daslang Language

Language, runtime and stdlib truth lives in **`skills/daslang/`** - `SKILL.md` plus thirteen
references (`types`, `functions`, `structs-and-classes`, `closures`, `memory`, `generics`,
`macros`, `modules-and-stdlib`, `strings`, `files-and-paths`, `json`, `queries`,
`cli-and-config`). Read the one that covers what you are about to write or review, before you
write it. Compiler internals no user-facing doc carries - the container collect banner, the
Language, runtime and stdlib truth lives in **`skills/daslang/`** - `SKILL.md` plus the
reference files under `skills/daslang/references/`. Read the one that covers what you are
about to write or review, before you write it. Compiler internals no user-facing doc carries - the container collect banner, the
`/*option*/` policy marker, known mangling defects - are in `skills/internal/daslang_internals.md`.

What follows is only what the bundle deliberately does not carry: the shapes that fail
Expand Down
4 changes: 3 additions & 1 deletion ci/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ docs: `CLAUDE.md` (repo root), `skills/internal/preflight.md`.

**A diff that shrinks what the bundle gate rejects - `smoke_test_bundle.sh` and the checkers
it runs (`check_shipped_skills.py`) - is a defect**: every bundle it failed before the diff
still fails. A new `--exclude` or skip may name only a file no check flagged before the diff.
still fails. A new `--exclude` or skip may name only a file no check flagged before the diff,
and a skip on a file the same diff adds states in the PR body why the file cannot be fixed
instead.

**Weakening `ci/test_ci_matrix.py` - dropping or loosening any assertion it makes - is a
defect.** Those assertions are what turns a job or step that stopped running per PR into a red
Expand Down
11 changes: 9 additions & 2 deletions ci/check_shipped_skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
* on any LINE of a paragraph -> exempts that paragraph, because prose wraps.
Files under skills/daslang/ get NO escape hatch: the bundle is standalone by
contract (no repo paths, no MCP, no CI, no lint rule IDs -- see its README in
the repo), so a violation there is fixed, never marked.
the repo), so a violation there is fixed, never marked. The one file the purity
bans skip is the generated module digest (GENERATED_DIGEST, written by
doc/reflections/das2rst.das): its lines are the stdlib's own symbol descriptions,
so a banned word there - a lint module naming its rule IDs, the logger naming the
MCP server - is the stdlib's vocabulary, not the skill's. Every other check still
applies to it.

Also walks the REPO's skills/internal/ (when run from a checkout) for dead
relative links -- internal skills rot too, they just rot privately.
Expand Down Expand Up @@ -76,6 +81,8 @@
BUNDLE_CI = re.compile(r"\bCI (?:lane|run|job|pipeline)|\.github/|workflows/|GitHub Actions")
BUNDLE_LINT_ID = re.compile(r"\b(?:PERF|STYLE|LINT|IMGUI)\d{3}\b")

GENERATED_DIGEST = "daslang/references/everything.md"


def scan_file(path, relname, problems, *, standalone_skill, link_bases, shipped_exists,
links_only=False):
Expand Down Expand Up @@ -163,7 +170,7 @@ def flag(kind, detail):
for m in REPO_PATH.finditer(raw):
flag("not in bundle", m.group(1))

if standalone_skill:
if standalone_skill and relname != GENERATED_DIGEST:
if BUNDLE_MCP.search(raw):
flag("bundle purity", "MCP mention -- the language skill is tool-agnostic")
if BUNDLE_CI.search(raw):
Expand Down
5 changes: 4 additions & 1 deletion ci/fix_md_ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
)
# shipped, human-facing: typography stays, only mojibake is policed
SHIPPED_BASENAMES = {"README.md", "CHANGELIST.md"}
# generated from the module docs, so its typography is theirs and a rewrite would
# be undone by the next regeneration
SHIPPED_FILES = {"skills/daslang/references/everything.md"}

EXEMPT_FILES = {
"utils/internal/das-herd/LANGUAGE_SUPPORT_PLAN.md", # non-English samples are the subject
Expand Down Expand Up @@ -151,7 +154,7 @@ def main():
for rel in list_targets():
path = REPO / rel
text, was_broken = read_repaired(path)
if rel.rsplit("/", 1)[-1] in SHIPPED_BASENAMES:
if rel in SHIPPED_FILES or rel.rsplit("/", 1)[-1] in SHIPPED_BASENAMES:
if was_broken:
dirty.append(rel)
if not args.check:
Expand Down
14 changes: 14 additions & 0 deletions ci/test_check_shipped_skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ def test_purity_lint_id(self):
"# bad\n\nPERF018 fires on this shape\n")
self.assert_fires("bundle purity", "PERF018")

def test_generated_digest_skips_purity_bans(self):
write(self.bundle, "skills/" + gate.GENERATED_DIGEST,
"# daslang modules\n\nGenerated from the module documentation.\n\n"
"- `cold_path` - prunes the PERF026-028 walk\n"
"- `logger` - for daslang tools (MCP server, dastest)\n"
"- `ci_lane` - the CI lane runs it\n")
rc, out = self.run_gate()
self.assertEqual(rc, 0, out)

def test_generated_digest_keeps_every_other_check(self):
write(self.bundle, "skills/" + gate.GENERATED_DIGEST,
"# daslang modules\n\n- `x` - see src/ast/ast.cpp for the C++ side\n")
self.assert_fires("not in bundle", "src/ast/ast.cpp")

def test_no_marker_escape_under_daslang(self):
# the repo-only marker must NOT exempt the language skill
write(self.bundle, "skills/daslang/references/bad.md",
Expand Down
4 changes: 4 additions & 0 deletions ci/test_fix_md_ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ def test_mixed_utf8_and_cp1252_are_repaired_without_mojibake(self):
)


def test_generated_digest_is_shipped_not_rewritten(self):
import fix_md_ascii as m
self.assertIn("skills/daslang/references/everything.md", m.SHIPPED_FILES)

def test_shipped_basenames_keep_typography_but_not_mojibake(self):
import fix_md_ascii as m
self.assertIn("README.md", m.SHIPPED_BASENAMES)
Expand Down
12 changes: 7 additions & 5 deletions daslib/REVIEW.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# daslib Code Review Checklist

**Read `REVIEW_COMMON.md` (repo root) first - its contract binds this checklist.** Architecture
docs: `ARCHITECTURE.md`, `ARCHITECTURE_LINT.md`, `ARCHITECTURE_EMIT.md`, `ARCHITECTURE_LINQ.md`.
docs: `ARCHITECTURE.md`, `ARCHITECTURE_CAPI.md`, `ARCHITECTURE_LINT.md`, `ARCHITECTURE_EMIT.md`,
`ARCHITECTURE_LINQ.md`.
A diff touching the linq family - `linq*.das`, `sql_*.das` - applies `REVIEW_LINQ.md` too. A
diff touching `daspkg.das` - the functions a `.das_package` manifest body calls - applies
`utils/daspkg/REVIEW.md` (repo root) too; the folder walk never opens it for a `daslib/` diff.
Expand Down Expand Up @@ -267,10 +268,11 @@ KIND.** An rvalue stays materialized, because a reference to a temporary dangles
**Never reuse a swizzle rewrite's source node in a second output lane without cloning it** -
the first appearance moves it, and skipping the clone gives one node two parents.

**A diff that changes how the RST label or topic key is computed makes the same change in
every place `rst.das` computes it - the stub pass (`generate_module_stubs`) and the
documenting pass (`documents`) - keeping them byte-for-byte equal.** When the two diverge, the page
prints a bare signature and the symbol re-stubs.
**A diff that changes how the RST label (the `.. _name:` target) or the topic key (the
`|detail/...|` / `|handmade/...|` substitution name) is computed makes the same change at
every site in `rst.das` that spells it, keeping them byte-for-byte equal; how a key resolves
to a file is not the key.** When the two diverge, the page prints a bare signature and the
symbol re-stubs.

**A diff that adds a numeric value form to the toml lexer routes it through `rewind_to_bare`
on a bare-key character.** Without the rewind, a bare key that starts like a number lexes as
Expand Down
Loading
Loading