Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c70c339
dasLLAMA vulkan: prefill overlap + device-side embed gather + merged …
borisbat Aug 27, 2026
6159327
dasLLAMA vulkan: cm2 kernel parity - coopmatClamp Unroll + the 16-bit…
borisbat Aug 28, 2026
83e0b80
dasLLAMA vulkan: attention-chain K/V host DMA moves to the end of the…
borisbat Aug 28, 2026
b14bd9a
dasLLAMA vulkan: wave-efficiency cm2 tile pick + cm2 becomes the coop…
borisbat Aug 28, 2026
5210d56
dasLLAMA: followup_vulkan item 11 - the (b)/(c) closure entry
borisbat Aug 28, 2026
230f26a
dasLLAMA vulkan: mode-4 ar fusion - the fused add+rms twin grows an f…
borisbat Aug 28, 2026
9cc6def
dasLLAMA vulkan: the wg_blk0 push-constant lever closes as measured-no
borisbat Aug 28, 2026
47b60f3
dasLLAMA vulkan: the merged k|v prefill GEMM serves mode 4 too
borisbat Aug 28, 2026
b78bdb2
dasLLAMA vulkan: the cm2 fa tile grows an f16-out stamp - mode 4 skip…
borisbat Aug 28, 2026
5d5c3ca
dasLLAMA: followup_vulkan item 11 - the mode-4 chain-thinning day banked
borisbat Aug 28, 2026
362e777
dasSpirv/dasLLAMA: small-int SSBO stores - the requant writers drop t…
borisbat Aug 28, 2026
70cf928
dasLLAMA: followup item 11 - the small-int store ledger closes
borisbat Aug 28, 2026
ac89ad9
dasLLAMA vulkan: Q4_K joins the cm2 prefill - decode-in-load over the…
borisbat Aug 28, 2026
6dad289
dasLLAMA: followup item 11 - the Q4_K cm2 entry
borisbat Aug 28, 2026
5e3be08
dasLLAMA vulkan: Q6_K cm2 tiles land oracle-gated but stay PINNED off…
borisbat Aug 28, 2026
68161b3
dasLLAMA: followup item 11 - the Q6_K pinned entry
borisbat Aug 28, 2026
4f15f3d
dasLLAMA vulkan: the k6 cliff was ONE byte4 dynamic select - Q6_K unp…
borisbat Aug 28, 2026
04779d3
dasLLAMA: followup item 11 - the k6 cliff closure + the decode select…
borisbat Aug 28, 2026
86caaf6
dasLLAMA vulkan: the PR round - harvest landings, review fixes, the m…
borisbat Aug 28, 2026
bb78a03
Merge remote-tracking branch 'origin/master' into bbatkin/vkclass
borisbat Aug 28, 2026
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
7 changes: 5 additions & 2 deletions .claude/agents/harvester.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ other filing unnecessary. Only a comment no name can carry goes on to the rest.
`REVIEW.md`, rewritten as a ban or duty per `REVIEW_COMMON.md`. Delete the comment.
- **FACT** - it states how the system is or why its shape wins. Propose it for the
architecture doc, as a present-tense statement per `ARCHITECTURE_COMMON.md`, naming the
section it joins. Delete the comment.
section it joins, the `{#anchor}` that section carries (or the one to mint), and the CITER -
the function the comment sat on, which gets `[arch(at="<doc>#<anchor>")]` when the fact
lands. A FACT without a citer is not filed: it is KEEP or DROP. 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, spelled `//!` - a contract comment, legal on
any visibility (a private `//!` caps at 3 lines under STYLE015). A comment already in the
Expand Down Expand Up @@ -59,7 +61,8 @@ Your final message is the ledger, nothing else:

1. Counts first: N comments -> R RULE / F FACT / K KEEP / D DROP / RN RENAME / T TODO.
2. Every RULE, FACT, and TODO: the original comment (condensed to its point), the exact
proposed destination text, and the destination (REVIEW.md; arch doc + section; ledger).
proposed destination text, and the destination (REVIEW.md; arch doc + section + anchor +
citer, as `file:def name`; ledger). A FACT line missing its citer is an incomplete ledger.
Every RENAME: the comment, current name -> proposed name, one line on what the new name
carries.
3. KEEP entries only where you compressed: before -> after, one line each.
Expand Down
5 changes: 5 additions & 0 deletions .claude/hooks/LAWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# LAWS - .claude/hooks

| date | document | ruling |
|---|---|---|
| 2026-08-28 | README.md (the stdin-only rule now admits the files the payload names; arch_inject.py section) | Boris: "we will land the pr, make the hook, and try on next session. and i will ask u to asses it towards the end - i.e. if the noise is too much, if it was of any use" + "how do we prevent repeating ourselves like crazy?" - the [arch] section arrives on the first edit inside a cited function, once per anchor per session, memo reset on compaction |
19 changes: 16 additions & 3 deletions .claude/hooks/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Claude Code hooks

Hooks for agent sessions in this repo. **A hook reads only its stdin payload -
no daslang, no config reads - and returns in tens of milliseconds.** It must
work when the das binary is down.
Hooks for agent sessions in this repo. **A hook reads only its stdin payload, the
file that payload names, and the documents that file cites - no daslang, no config
reads - and returns in tens of milliseconds.** It must 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
Expand All @@ -19,6 +20,18 @@ use instead is `daslang utils/internal/pr-babysit/main.das -- --pr <N> --watch`,
run bare in a background Bash (exit code is the verdict). A single un-looped
`gh pr checks <N>` from Bash passes.

## arch_inject.py - PostToolUse, `Edit|Write|MultiEdit`

When an edit lands inside a `.das` function carrying `[arch(at="<doc>.md#<anchor>")]`,
the hook returns the cited section as `additionalContext` - the 40 lines that govern the
function arrive when the function is touched, instead of a 300-line document being read
first. Once per anchor per session: a memo in the temp directory
(`claude-arch-memo-<session_id>.json`) keeps each anchor's section hash, so twelve citers
of one section cost one injection and an edited section re-injects. `--reset` (registered
on `PreCompact` and `SessionEnd`) drops the memo, because after a compaction the earlier
copy has left the context. Sections cap at 60 lines; `arch_of` returns the rest. Reads and
`arch_of` stay quiet - the moment that matters is writing.

## Registration

The tracked `.claude/settings.json` registers hooks for every checkout;
Expand Down
181 changes: 181 additions & 0 deletions .claude/hooks/arch_inject.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#!/usr/bin/env python3
"""PostToolUse hook (Edit|Write|MultiEdit): when the edit lands inside a function that carries
[arch(at="<doc>.md#<anchor>")], hand the cited section to the model - once per anchor per
session (a memo keyed by anchor and section hash), so twelve citers of one section cost one
injection. `--reset` (PreCompact / SessionEnd) drops the memo: after a compaction the earlier
copy left the context, so the next edit re-injects. Reads only stdin plus the files it names."""

import hashlib
import json
import os
import re
import sys
import tempfile

CITE = re.compile(r'arch\s*\(\s*at\s*=\s*"([^"#]+)#([^"]+)"')
DEF = re.compile(r'^\s*def\b')
HEADING = re.compile(r'^(#{1,6})\s+.*\{#([^}\s]+)\}\s*$')
MAX_LINES = 60


def memo_path(session_id):
return os.path.join(tempfile.gettempdir(), "claude-arch-memo-%s.json" % (session_id or "nosession"))


def load_memo(path):
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return {}


def save_memo(path, memo):
try:
with open(path, "w", encoding="utf-8") as f:
json.dump(memo, f)
except Exception:
pass


def read_text(path):
try:
with open(path, "r", encoding="utf-8", errors="replace") as f:
return f.read()
except Exception:
return ""


def citations_above(lines, def_index):
"""The [arch] citations in the annotation block directly above a def line."""
found = []
i = def_index - 1
while i >= 0:
t = lines[i].strip()
if t == "" or t.startswith("//"):
i -= 1
continue
if t.startswith("[") or t.endswith("]") or t.endswith(","):
found.extend(CITE.findall(t))
i -= 1
continue
break
return found


def enclosing_citations(text, offset):
"""Citations of the function whose body holds `offset` (or the annotation block the edit sits in)."""
lines = text.split("\n")
line_no = text.count("\n", 0, max(offset, 0))
for i in range(min(line_no, len(lines) - 1), -1, -1):
if DEF.match(lines[i]):
return citations_above(lines, i)
# an edit on the annotation block itself
if CITE.search(lines[i]) and i >= line_no:
return CITE.findall(lines[i])
return []


def all_citations(text):
return CITE.findall(text)


def section_of(doc_text, anchor):
lines = doc_text.split("\n")
start = -1
level = 0
for i, line in enumerate(lines):
m = HEADING.match(line.rstrip("\r"))
if m and m.group(2) == anchor:
start = i
level = len(m.group(1))
break
if start < 0:
return ""
stop = len(lines)
for i in range(start + 1, len(lines)):
m = re.match(r'^(#{1,6})\s', lines[i])
if m and len(m.group(1)) <= level:
stop = i
break
body = [l.rstrip("\r") for l in lines[start:stop]]
while len(body) > 1 and body[-1].strip() == "":
body.pop()
if len(body) > MAX_LINES:
body = body[:MAX_LINES] + ["... (section continues - `arch_of` returns it whole)"]
return "\n".join(body)


def main():
raw = sys.stdin.read()
try:
payload = json.loads(raw) if raw.strip() else {}
except Exception:
return 0
session = payload.get("session_id", "")
path = memo_path(session)
if "--reset" in sys.argv:
try:
os.remove(path)
except Exception:
pass
return 0
tool = payload.get("tool_name", "")
tin = payload.get("tool_input", {}) or {}
file_path = tin.get("file_path", "") or ""
if tool not in ("Edit", "Write", "MultiEdit") or not file_path.endswith(".das"):
return 0
text = read_text(file_path)
if not text or "arch" not in text:
return 0
cites = []
if tool == "Write":
cites = all_citations(text)
else:
edits = tin.get("edits", []) if tool == "MultiEdit" else [tin]
for e in edits:
needle = e.get("new_string", "") or e.get("old_string", "") or ""
if not needle.strip():
continue
# every occurrence: a repeated snippet cannot say which function took the edit,
# so each enclosing function's sections are owed (the memo folds the repeats)
at = text.find(needle)
hits = 0
while at >= 0 and hits < 16:
cites.extend(enclosing_citations(text, at))
hits += 1
at = text.find(needle, at + 1)
if not cites:
return 0
folder = os.path.dirname(os.path.abspath(file_path))
memo = load_memo(path)
out = []
seen_here = set()
for doc, anchor in cites:
doc_path = os.path.normpath(os.path.join(folder, doc)).replace("\\", "/")
key = "%s#%s" % (doc_path, anchor)
if key in seen_here:
continue
seen_here.add(key)
section = section_of(read_text(doc_path), anchor)
if not section:
continue
digest = hashlib.sha1(section.encode("utf-8")).hexdigest()
if memo.get(key) == digest:
continue
memo[key] = digest
rel = os.path.relpath(doc_path, payload.get("cwd", "") or os.getcwd()).replace("\\", "/")
out.append("[arch] %s#%s - the section this function answers for:\n%s" % (rel, anchor, section))
if not out:
return 0
save_memo(path, memo)
context = ("The function you just edited cites an architecture section. Keep the code true to it, "
"or change the section in the same diff (REVIEW_COMMON.md's [arch] audit duty).\n\n"
+ "\n\n".join(out))
print(json.dumps({"hookSpecificOutput": {"hookEventName": "PostToolUse",
"additionalContext": context}}))
return 0


if __name__ == "__main__":
sys.exit(main())
67 changes: 51 additions & 16 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,52 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Monitor|Bash",
"hooks": [
{
"type": "command",
"command": "jq -c -f \"$CLAUDE_PROJECT_DIR/.claude/hooks/monitor_guard.jq\"",
"timeout": 15,
"statusMessage": "PR-watch guard: pr-babysit is the tool"
}
]
}
]
}
{
"hooks": {
"PreToolUse": [
{
"matcher": "Monitor|Bash",
"hooks": [
{
"type": "command",
"command": "jq -c -f \"$CLAUDE_PROJECT_DIR/.claude/hooks/monitor_guard.jq\"",
"timeout": 15,
"statusMessage": "PR-watch guard: pr-babysit is the tool"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/arch_inject.py\"",
"timeout": 10,
"statusMessage": "[arch] section for the edited function"
}
]
}
],
"PreCompact": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/arch_inject.py\" --reset",
"timeout": 5
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/arch_inject.py\" --reset",
"timeout": 5
}
]
}
]
}
}
8 changes: 5 additions & 3 deletions .github/workflows/extended_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -365,15 +365,17 @@ jobs:
# build/doc_verify holds .das extracted verbatim from RST by the doc-verify step above - not authored source
$BIN/das-fmt.exe --path ./ --verify --exclude-mask build/

- name: "Run lint on changed .das files"
- name: "Run lint on changed .das and .md files"
if: matrix.target == 'linux'
run: |
set -eux
BASE_REF="${{ github.event.pull_request.base.ref }}"
BASE_REF="${BASE_REF:-master}"
mapfile -t CHANGED < <(git diff --name-only --diff-filter=AM "origin/${BASE_REF}...HEAD" -- '*.das')
# a changed .md arms its folder's document rules (LINT025/026/027) with no .das compiled;
# a repo-root .md arms the whole tree - intended, and a few seconds with nothing to compile
mapfile -t CHANGED < <(git diff --name-only --diff-filter=AM "origin/${BASE_REF}...HEAD" -- '*.das' '*.md')
if [ ${#CHANGED[@]} -eq 0 ]; then
echo "no .das files changed; skipping lint"
echo "no .das or .md files changed; skipping lint"
exit 0
fi
echo "linting: ${CHANGED[*]}"
Expand Down
9 changes: 9 additions & 0 deletions ARCHITECTURE_COMMON.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ and the exception ledger. Nothing else.**
**Sections are numbered, and rules cite them by section.** A section number is never reused
for different content: append new sections, never renumber.

**A section that code implements carries a `{#anchor}` on its heading, and every anchor is
cited by an `[arch(at="<doc>#<anchor>")]` on a function in the document's own folder tree.**
One anchor per heading; the anchor name is stable across rewording, like the section number.
An anchor no function cites, a citation naming no anchor, and a citation reaching a document
outside the citer's folder tree are all lint findings (LINT026), in every folder. A mechanism
another folder's document states is restated here in prose - a paragraph, not a resolved link -
and the code cites this document. A section no function implements is narrative and carries no
anchor.

**A fact that a rule or a code comment cites is load-bearing: it must stay true.** The
same-change duty that keeps it true belongs in the folder's `REVIEW.md`, not here.

Expand Down
10 changes: 5 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ cites.** MCP `arch_of` returns each of a file's citations with its section text;
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.
**An architecture-doc heading that code cites carries the `{#anchor}` its citation names, and
every anchor is cited.** LINT026 fails a citation naming no such file or anchor, and - in every
folder, no tag arms it - an anchor no `[arch]` cites. An `[arch]` citation replaces the comment
that would have restated the section: the mechanism lives in the document, the code names it.

**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** -
**A `REVIEW*.md` or `ARCHITECTURE*.md` past 300 lines, wherever it sits, 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.
Expand Down
3 changes: 3 additions & 0 deletions LAWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ compacted, or cited as rules.
| 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 |
| 2026-08-27 | REVIEW_COMMON.md (the [arch] audit triangle) | "1. if function with [arch(section)] is modified, other functions which link that section are audited. 2. if [arch(foo#section)] is modified, section gets audited to not go stale. 3. if foo#section is modified, all linked functions are audited." + on scope: "repo-wide from day one." - three constitutional rules after the ships-with-tests clause; one pass per anchor discharges all duties, no cascade |
| 2026-08-28 | CLAUDE.md (document system), daslib/lint_config.das, utils/lint (LINT026 reverse + LINT027 arming), modules/dasLLAMA/.lint_config (deleted), utils/lint/README.md | "remove enable_arch link option entirely. its now mandatory." + "the idea is that arch lnks replace comments, where necessary" - the [arch] reverse pass runs in every folder with no tag; the LINT027 line gate arms on any folder holding a rule document; a citation replaces the comment that would restate the section (the harvester deletes the leftovers) |
| 2026-08-28 | REVIEW_COMMON.md (harvest duty), ARCHITECTURE_COMMON.md (anchor form), .claude/agents/harvester.md (FACT names its citer), skills/internal/make_pr.md (row 0a0) | "i would like to ensure that harvested sections of architecture.md are linked to appropriate functions. im thinking a section in REVIEW_COMMON.md should be able to cover it" - a filed FACT lands as statement + anchor + citation from the source function in the same change; the harvester ledger names the citer or the fact is not filed |
| 2026-08-28 | ARCHITECTURE_COMMON.md (anchor form), doc/source/reference/language/lint.rst (LINT026), skills/mcp_tools.md, utils/common/arch_citations.das, .github/workflows/extended_checks.yml (changed-set glob) | "should cite own subtree. if need citation outside - make citation in architecture.md in own subtree, in text form. not like automatic cross-link we resolve, but just a paragraph" + lint updated .md on CI, "skipping should be very cheap" - an [arch] citation must target a document whose folder is the citer folder or an ancestor; CI passes changed .md to the lint (a .md positional arms its folder with no .das compiled) |
5 changes: 5 additions & 0 deletions REVIEW_COMMON.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ describes this function; verify it does.
audit pass over an anchor's section text and citer set discharges every audit duty the diff
triggers on that anchor - the duties never cascade.

**A diff that moves a fact out of a function's comment into an `ARCHITECTURE*.md` lands three
things in the same change: the statement, a `{#anchor}` on the heading of the section it joins,
and an `[arch(at=...)]` citation on that function - and the comment goes.** The citation is
what keeps the section true: a section nothing cites is never re-checked when the code changes.

**A rule that a test, a lint, or the folder's `REVIEW.das` enforces is deleted.** Automation
replaces the rule; the checklist keeps at most "weakening that check is a defect." A rule
that COULD be automated is a lint or `REVIEW.das` candidate - say so in the review round.
Expand Down
5 changes: 4 additions & 1 deletion ci/smoke_test_bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,11 @@ run_check "mcp.das (empty stdin)" bash -c \
run_check "dastest.exe runs a shipped suite" bash -c \
"set -o pipefail; '$BUNDLE/bin/dastest${DASEXE_SUFFIX}' --test utils/common/tests --isolated-mode | tee '$LOG.suite' \
&& grep -Eq '^[1-9][0-9]* tests, [1-9][0-9]* passed, 0 failed, 0 errors' '$LOG.suite'"
# LINT026 is off here by construction: an [arch] citation names an ARCHITECTURE*.md, and
# those documents never ship (see the leak check below), so in the bundle every citation
# in daslib is a dangling one. The source tree's lint lanes verify the citations.
run_check "lint.exe lints daslib, no skips" bash -c \
"set -o pipefail; '$BUNDLE/bin/lint${DASEXE_SUFFIX}' daslib | tee '$LOG.lint' \
"set -o pipefail; '$BUNDLE/bin/lint${DASEXE_SUFFIX}' daslib --disable LINT026 | tee '$LOG.lint' \
&& grep -Eq '^[0-9]+ files, 0 issue\(s\), 0 error\(s\)\$' '$LOG.lint'"

# Shipped skills must not send the reader to a path the bundle does not contain.
Expand Down
Loading
Loading