install: ship what the docs promise + close the smoke-test hole that hid it - #3571
Conversation
…hid it
Audited `cmake --install` coverage against the tree. Seven gaps broke workflows
the *shipped* docs tell users to follow; the worst is that `utils/mcp/setup.das`
has never been installed, while the installed `utils/mcp/README.md` and the
shipped `skills/mcp_tools.md` both document running it. The MCP bootstrap was
impossible from a bundle through 0.6.4.
Root cause of the class: ci/smoke_test_bundle.sh compiled 9 of the 14 installed
.das entry points, and setup.das sat in the gap, so nothing ever noticed. All 14
are covered now (12 checks -> 17).
Ship what was missing:
- utils/mcp/setup.das + mcp_supervisor.py (the documented bootstrap).
- utils/mcp/tests/ non-.das fixtures. `FILES_MATCHING PATTERN "*.das"` dropped
_fixture_cpp_outline.h and _pretend_root/.../.das_module, both required by the
installed test_tools.das, so the suite shipped unable to run those cases.
- utils/lint/tests/ (77 files), so a bundle can self-check the linter. Verified:
51 tests, 51 passed via dastest inside the install tree.
- examples/daStrudel/sfx_lab sounds/*.sfx + .das_package. The scripts read these
via get_das_root(); shipping the scripts alone left them broken.
- examples/graphics per-example .das_package + .gitignore. Each subdir is a
daspkg -project-root whose release_main points at the shared source one level
up, so the non-recursive glob dropped the load-bearing manifests.
- examples/benchmarks/, documented in the installed examples/README.md.
- aot_testing / llvm_tune / perf_lint / style_lint skills, cross-referenced by
already-shipped skills. tutorials.md deliberately stays repo-only and the one
reference to it (skills/xml.md) is reworded instead, since shipping it would
drag in documentation_rst.md and onward.
- tree-sitter-daslang/zed-daslang/, which install/README.md points users at.
- CHANGELIST.md: a versioned bundle had no release notes.
- integration_cpp_23 in the standalone tutorial recipe. The source shipped with
no way to build it; handle_registry.h was already installed.
Decouple tutorial data install from DAS_TUTORIAL_DISABLED. The install rules for
all 79 C/C++ integration tutorial sources lived inside the gated include(), so
"don't build the tutorial executables" silently also meant "don't ship the
tutorial sources". release.yml never sets the flag, so shipping was fine today.
Verified by flipping it: 50 integration-source refs survive in the install script.
Hygiene:
- Drop `FLEX(utils/dasFsormatter/ds_lexer.lpp)`: typo'd dir that does not exist,
and dasFormatter has no .lpp at all. Inert only because no target consumed the
output path.
- examples/daspkg used a hardcoded DESTINATION instead of DAS_INSTALL_EXAMPLESDIR,
and neither it nor examples/games excluded modules/ or build output, so a dev
tree would ship daspkg junk.
- file(STRINGS) on install/skills.list now passes ENCODING UTF-8. Without it,
non-ASCII bytes act as separators: an em-dash in a comment splits the line and
the tail is read as a skill filename, failing the guard with a nonsense path.
Also fix the dasHV tutorial artifact that got committed: the server saves
{upload_dir}/_testfile.txt but cleanup_upload_dir removed {dir}/testfile.txt (no
underscore), so the file survived, remove(dir) failed on a non-empty dir, and
_upload_test/_testfile.txt landed in git. Fix the name, untrack the file,
gitignore the run dirs. Correct the Zed extension path in both READMEs
(zed-daslang/, not editors/zed/).
Record the durable rules in skills/install_instructions.md: the shipped-skill
closure invariant with a check script, and the ASCII-only rule for skills.list.
Verified end to end: release-flag bundle installed to a scratch prefix and diffed
against the pre-fix bundle -- exactly 134 files added, nothing unintended;
smoke test 17/17; zero dangling skill-to-skill references across 33 shipped skills.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WiXc1jvihNmEnU7DDQidvt
There was a problem hiding this comment.
Pull request overview
This PR tightens the SDK/bundle install surface so cmake --install actually ships the files and fixtures that the shipped documentation and examples reference, and extends the bundle smoke test to compile every installed .das entry point to catch future install gaps.
Changes:
- Move C/C++ integration tutorial source installation out of
DAS_TUTORIAL_DISABLED-gated CMake includes so tutorial sources always ship, and extend the standalone tutorial recipe to include tutorial 23. - Expand installed content for MCP + lint tooling and examples (fixtures/tests, Strudel sfx_lab data, benchmarks, tree-sitter Zed extension), and update docs to match shipped paths.
- Strengthen smoke-test coverage and clean up accidental tutorial artifacts via corrected cleanup +
.gitignorerules.
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tutorials/integration/cpp/CMakeLists.txt | Removes local install rules and documents that tutorial-source installs live in tutorials/CMakeLists.txt. |
| tutorials/integration/cpp/CMakeLists.standalone.cmake | Adds standalone build recipe entry for integration_cpp_23. |
| tutorials/integration/c/CMakeLists.txt | Removes local install rules and explains why installs must be unconditional. |
| tutorials/dasHV/05_cookies_and_forms.das | Fixes cleanup to remove the correct uploaded test filename, preventing leftover artifacts. |
| tutorials/dasHV/_upload_test/_testfile.txt | Removes an accidentally committed runtime artifact. |
| tutorials/CMakeLists.txt | Adds unconditional install rules for C/C++ integration tutorial sources + standalone CMakeLists. |
| skills/xml.md | Rewords tutorial-data install guidance to avoid referencing a repo-only skill and to point at the actual globbing behavior. |
| skills/install_instructions.md | Documents shipped-skill closure and skills.list encoding constraints + a check script. |
| README.md | Fixes Zed extension path under tree-sitter-daslang/. |
| modules/dasAudio/CMakeLists.txt | Installs .sfx and .das_package for Strudel sfx_lab so shipped scripts can run. |
| install/skills.list | Adds shipped-skill closure invariant notes and ships additional cross-referenced skills. |
| install/README.md | Fixes Zed extension path under tree-sitter-daslang/. |
| install/CLAUDE.md | Adds entries for newly shipped skills in the SDK-facing skill table. |
| CMakeLists.txt | Adds missing installed files (e.g., MCP setup + supervisor, lint tests, examples/benchmarks, zed extension, CHANGELIST) and improves install hygiene/excludes. |
| ci/smoke_test_bundle.sh | Expands compile-only coverage to all installed .das entry points and clarifies bundle executable expectations. |
| .gitignore | Ignores tutorial runtime artifacts (dasHV upload/static dirs and dasAudio tutorial WAVs) to prevent re-commits. |
Comments suppressed due to low confidence (2)
tutorials/CMakeLists.txt:144
- Same as above: add
CONFIGURE_DEPENDSso newly added/removed C/C++ integration tutorial sources are picked up without requiring a manual CMake reconfigure, which helps keep install coverage correct over time.
file(GLOB CPP_INTEGRATION_TUTORIAL_SOURCES
CMakeLists.txt:2127
- Same concern as the graphics install: if the source tree contains daspkg/runtime artifacts (lock/log/tmp dirs, shared_module outputs, jitted_scripts, etc.), they will be copied into the installed SDK because they are not excluded here.
install(DIRECTORY ${PROJECT_SOURCE_DIR}/examples/benchmarks/
DESTINATION ${DAS_INSTALL_EXAMPLESDIR}/benchmarks
FILES_MATCHING
PATTERN "*.das"
PATTERN "*.md"
PATTERN ".das_package"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # These are UNCONDITIONAL on purpose: DAS_TUTORIAL_DISABLED means "don't build the | ||
| # tutorial executables", not "don't ship the tutorial sources". The rules used to | ||
| # live inside the two include()d files below, which coupled the two. | ||
| file(GLOB C_INTEGRATION_TUTORIAL_SOURCES |
| install(DIRECTORY ${PROJECT_SOURCE_DIR}/examples/graphics/ | ||
| DESTINATION ${DAS_INSTALL_EXAMPLESDIR}/graphics | ||
| FILES_MATCHING | ||
| PATTERN "*.das" | ||
| PATTERN ".das_package" | ||
| PATTERN ".gitignore" | ||
| PATTERN "README.md" | ||
| PATTERN "modules" EXCLUDE | ||
| PATTERN ".daspkg_cache" EXCLUDE | ||
| PATTERN ".jitted_scripts" EXCLUDE | ||
| PATTERN "_aot_generated" EXCLUDE | ||
| ) |
…at can't ship
Follow-up to the install audit in this PR. The shipped skills sent readers to 70
repo paths that a bundle never contains. Two problems were tangled together there,
and they need opposite fixes.
Where the skill relies on the content, the content now SHIPS, as markdown, with
exactly one source file. Teach Sphinx to read markdown (myst-parser==2.0.0, the
last line supporting sphinx 7.2.6) and each .rst becomes a ~13-line pointer that
includes the .md via `.. include:: ... :parser: myst_parser.sphinx_`. daslang.io
and the SDK then read the same bytes, so they cannot drift, and there is no
generated artifact to keep in sync. Converted this way, and added to
install/skills.list:
skills/design_philosophy.md (was reference/design_philosophy.rst)
skills/tune.md (was reference/tune.rst)
skills/profiler.md (was reference/utils/profiler.rst)
skills/linq_fold_patterns.md (was reference/linq_fold_patterns.rst)
skills/detect_dupe_reference.md (was reference/utils/detect_dupe.rst)
Two of those RST pages share a stem with an existing shipped skill, because they
are the same topic twice. They are NOT the same case. memory_leak_detection.md
said outright that its RST "covers the same material in docs style", so that
pointer is simply reworded and nothing new ships — four of its five references now
resolve to skills/profiler.md, inside the bundle. detect_dupe.rst is genuinely
fuller than its skill (541 lines, five flag tables), so it ships under a
non-colliding name. Breadcrumb pointers in json.md / regex.md / das_macros.md
("RST companion at", "generated stdlib reference at" — two of them naming
stdlib/generated files that do not exist in a fresh checkout) point at the
published page instead.
Where the path is engine internals, the answer is the reverse of shipping it.
src/, tests/, benchmarks/ and modules/*/src are never going into a bundle, so the
line now says so with a repo-only token, and the reader skips it instead of
hunting a path that is not there. 21 refs marked: two heading retitles cover 7
(cpp_integration's "C++ Codebase Notes", jobque_debugging's "Key files"), and 12
one-off prose mentions are marked inline so the sentence stays with the point it
supports.
Enforced per-PR by ci/check_shipped_skill_refs.awk, run from
ci/smoke_test_bundle.sh (build.yml's bundle_smoke job, which triggers on
pull_request) — no new CI wiring. Smoke test 17 -> 18 checks. Exemption is
SECTION-scoped and resets at each heading: a trailing-marker rule would leak the
exemption through the rest of the file, which is wrong for cpp_integration.md
where the internals section sits mid-file. Fenced blocks are exempt because they
quote tool output verbatim, including a compiler warning that literally prints a
doc/source path. tests/ is deliberately not in the pattern yet (53 refs, 24 of
them in aot_testing.md) — that class still needs sorting into inline-the-snippet
vs quarantine, and the awk says so.
Verified, not assumed:
* docs built with CI's exact command (sphinx-build -W --keep-going): ZERO new
warnings, six removed, against a 282-line baseline. Page labels had to move
into the .rst stubs, because a MyST (label)= target does NOT register in
Sphinx's std domain when the markdown arrives through an include with
:parser:; and two bare :ref: uses needed explicit link text once the title
moved into the markdown.
* the checker negative-tested: clean passes; an unmarked src/ path fails with
file:line; the same line marked repo-only passes; a fenced path is ignored.
* doc/source citations from shipped skills: 9 -> 1, and that one is a compiler
warning quoted inside a fence, which must stay verbatim.
* bundle reinstalled; 38 skills ship; zero dangling skill-to-skill references.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WiXc1jvihNmEnU7DDQidvt
| install(DIRECTORY ${PROJECT_SOURCE_DIR}/examples/daStrudel/ | ||
| DESTINATION ${DAS_INSTALL_EXAMPLESDIR}/daStrudel | ||
| FILES_MATCHING | ||
| PATTERN "*.das" | ||
| PATTERN "*.md" | ||
| PATTERN "*.sfx" | ||
| PATTERN ".das_package" | ||
| ) |
…ow to write a skill
Three pieces: a per-PR gate for what a script can check, a review skill for what it
can't, and a CLAUDE.md section so the decision gets made before the writing.
ci/check_shipped_skills.py replaces the awk from the previous commit. The link check
needs to tell a missing file from a directory, which awk cannot do portably, so this is
Python — invoked from ci/smoke_test_bundle.sh and skipped (not failed) when no
interpreter is present, so the script stays runnable on a bare box. Five classes, all in
a SHIPPED skill:
* src/, doc/source/, benchmarks/, modules/*/{src,tests,tutorial,harness}
* bin/Release|Debug/... -- the Windows repo layout; a bundle has bin/daslang
* daslang.exe <script> -- .exe is Windows-only
* C:\Users\..., /home/<name>/..., AppData -- someone's machine in a doc
* a relative link whose target is absent from the bundle
* skills/<other>.md where <other> is not shipped (the closure invariant, ported over)
It found 34 real hits, all now fixed. 14 were bin/Release/daslang.exe -- including the
first three lines of das_formatting.md, i.e. instructions that are wrong on two of three
platforms. 8 were dead links, 3 named generated .rst that exists nowhere, 9 were .exe
invocations.
Narrowness was the hard part, and two of my own patterns were wrong before they were
right. A naive absolute-path regex matched every http:// URL (77 false hits) and the
\\-UNC branch matched \\d and \\s in regex prose; that check is now scoped to
machine-local paths only, so the 17 deliberate C:/DummyRoot examples in
external_module_debugging.md stay quiet. The link resolver joined against the bundle root
while links are authored relative to skills/, which made 19 live links look dead. And the
.exe check flagged prose ("shared across `daslang.exe` and every module DLL") until it
required the next token to be a flag or a real file. A gate that cries wolf gets muted,
and then it is worse than no gate — so all 21 shapes are negative-tested: 9 must-fail, 10
false-positive shapes that must stay quiet, plus a check that a section-scoped repo-only
marker RESETS at the next heading instead of leaking down the file.
Also fixed while wiring it up: `command -v python3` finds the Windows Store shim, which
is on PATH but exits "Permission denied". The probe now executes the interpreter.
Split writing_tests.md, which was two audiences in one file. The universal dastest
guidance stays and ships; the repo's own harness — AOT registration for a new tests/ dir,
the tests/.das_test gating filter and its root-path caveat, per-folder sweep gating,
deep-engine model-test rules — moves to skills/tests_in_repo.md, deliberately NOT shipped.
The shipped half also now points at dastest/tests, which ships and doubles as a worked
example, instead of tests/linq, which does not. My first draft of the shipped file
referenced skills/tests_in_repo.md — the exact closure violation documented one commit
earlier — which is why the closure check is now enforced by the script rather than living
as a shell snippet in a doc.
New skills/writing_skills.md (repo-only) covers what no script can: pick the audience
BEFORE writing, because a mixed file serves neither and splitting it afterwards is a
reorganization rather than a cut (aot_testing.md is the standing example, still unsplit);
check whether an existing skill or doc/source page already owns the topic, since two
documents drifting apart beats one imperfect one; verify syntax claims by probe rather
than recall; and never silence the gate with a marker when the honest answer is a split.
CLAUDE.md gains a short "Writing a new skill" section pointing at it, plus a table row.
Verified: smoke test 18 checks green; gate exits 0 against the reinstalled bundle;
38 skills ship; tests_in_repo.md and writing_skills.md correctly absent from it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WiXc1jvihNmEnU7DDQidvt
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 57 out of 58 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
skills/profiler.md:60
- For SDK users running from the bundle root, this command should use
bin/daslang(notdaslangon PATH). Also consider changing the code fence language tobashsince this is a shell invocation.
| **`shutdown` tool.** Shuts down the MCP server process. Claude Code auto-restarts it, picking up code changes to `.das` tool files. Tool registration changes (adding/removing tools) still require a manual MCP restart. | ||
|
|
||
| **Configuration.** Configure `.mcp.json` with `"command"` pointing at the daslang binary (`bin/Release/daslang.exe` on Windows MSVC, `build/daslang` on Linux/macOS, `bin/daslang` for the installed SDK), `"args": ["utils/mcp/main.das"]`. See `utils/mcp/README.md` for details and Claude Code permissions. | ||
| **Configuration.** Configure `.mcp.json` with `"command"` pointing at the daslang binary (`bin/daslang` on Windows MSVC, `build/daslang` on Linux/macOS, `bin/daslang` for the installed SDK), `"args": ["utils/mcp/main.das"]`. See `utils/mcp/README.md` for details and Claude Code permissions. |
| Run any daslang script with `--das-profiler` and optionally a log-file path: | ||
|
|
||
| ```das | ||
| daslang --das-profiler --das-profiler-log-file /tmp/trace.json path/to/script.das |
…eeds it
aot_testing.md is the daslang repo's AOT test harness -- the test_aot binary, tests/aot
registration, libDaScriptAot regeneration, CI wiring. An SDK user has no way to act on any
of it, so it is not their skill and it no longer ships. That is simpler and more honest
than the split I was heading for, and it reverts churn: the six edits I had made to that
file were all gate-appeasement, including turning bin/Release/daslang.exe into bin/daslang,
which is a REGRESSION for Windows repo devs whose layout really is bin/Release. The file is
now byte-identical to master again.
The only shipped skill that referenced it was cpp_integration.md. Rather than drop the
pointer, that section now carries the actionable part inline -- generate stubs with
`bin/daslang -aot in.das out.cpp`, add -aot-macros for macros, regenerate on
error[50101] -- and names aot_testing.md as repo-only for the harness itself. install/
CLAUDE.md loses its row; install/skills.list explains WHY the file is absent, so the next
person does not re-add it to satisfy the closure invariant.
With aot_testing.md out and writing_tests.md already split, tests/ can finally join the
gate pattern. That surfaced 10 more refs in shipped skills, all worked-example pointers
into the repo test corpus (das_macros, dashv, daslib_modules, llvm_tune, xml, plus two in
my own new prose) -- each now marked rather than deleted, since they are useful to a repo
reader and simply absent for an SDK one.
The marker is now PARAGRAPH-scoped, not line-scoped. Two of those last ten hits were text
I had just written, where the marker landed one line away from the path because the
sentence wrapped -- twice. Scoping per-line means an author has to reflow prose to satisfy
the gate, which is exactly how a gate earns being muted. A marker anywhere in a paragraph
now covers it; the exemption still does not leak across a blank line, and heading-scoped
and line-scoped markers are unchanged. Verified both directions.
Two process traps hit while doing this, both worth knowing:
* `cmake --install` is ADDITIVE. Un-shipping a file leaves the old copy in the prefix, so
the gate ran green against a bundle that still contained aot_testing.md. Removing the
prefix first is the only way to see the real shipped set.
* install/skills.list is read at CONFIGURE time via file(STRINGS). Editing it and running
only `cmake --install` installs the OLD list. Reconfigure first.
Verified: fresh install ships 37 skills with aot_testing.md absent; gate exits 0; smoke
test 18 checks green; the full negative-test suite still passes (9 must-fail classes, 10
false-positive shapes that must stay quiet, section-marker reset, and the two new
paragraph-scope cases).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WiXc1jvihNmEnU7DDQidvt
Also adds ci/reinstall_bundle.sh: reconfigure + wipe prefix + install + verify in one
command, so the loop is a single reviewable invocation instead of an ad-hoc `rm -rf`. It
guards the delete -- refuses anything that is not absent or recognizably an installed
bundle, and refuses a source checkout outright -- and its comments encode the two traps
above so the next person does not rediscover them.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 59 out of 60 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (3)
skills/daslang_live.md:34
- The code block now uses the cross-platform
bin/daslang-livenaming, but this comment still saysdaslang.exe. Since the goal here is bundle-friendly docs, it should refer todaslang(orbin/daslang) rather than a Windows-only filename.
# Standalone mode (same as daslang.exe — if script only has main())
bin/daslang-live path/to/main.das
skills/daslang_live.md:37
- This sentence says scripts can be run with
bin/daslang ...but then refers to the non-live host asdaslang.exe. For consistency (and to avoid implying a Windows-only binary), this should saybin/daslang.
Scripts can also run standalone with `bin/daslang path/to/main.das` — the same `main.das` works in both hosts. Under `daslang.exe`, `is_live_mode()` returns `false`, the REST API does not start, and `[before_reload]`/`[after_reload]` annotations are ignored.
skills/install_instructions.md:41
- This enforcement note is stale: it still points at the old awk checker and claims
tests/is not in the pattern. The new Python gate includestests/and is whatci/smoke_test_bundle.shactually runs, so the instructions should match reality.
| **`shutdown` tool.** Shuts down the MCP server process. Claude Code auto-restarts it, picking up code changes to `.das` tool files. Tool registration changes (adding/removing tools) still require a manual MCP restart. | ||
|
|
||
| **Configuration.** Configure `.mcp.json` with `"command"` pointing at the daslang binary (`bin/Release/daslang.exe` on Windows MSVC, `build/daslang` on Linux/macOS, `bin/daslang` for the installed SDK), `"args": ["utils/mcp/main.das"]`. See `utils/mcp/README.md` for details and Claude Code permissions. | ||
| **Configuration.** Configure `.mcp.json` with `"command"` pointing at the daslang binary (`bin/daslang` on Windows MSVC, `build/daslang` on Linux/macOS, `bin/daslang` for the installed SDK), `"args": ["utils/mcp/main.das"]`. See `utils/mcp/README.md` for details and Claude Code permissions. |
|
|
||
| The CMake install rule (in root `CMakeLists.txt`) reads the manifest with `file(STRINGS ...)` and `install(FILES ...)` for each named basename. Missing files trigger `FATAL_ERROR` at configure time, so a typo in `install/skills.list` fails loudly. | ||
|
|
||
| **Closure invariant.** A shipped skill may only reference `skills/<other>.md` when that other skill also ships — otherwise the SDK carries a dead link. The rule cuts both ways: a genuinely repo-only skill (`tests_in_repo.md`, `tutorials.md`, `documentation_rst.md`, `preflight.md`, `make_pr.md`, …) stays **off** the list, and a shipped skill pointing at one either gets reworded or marks the line `repo-only` (see below) rather than dragging it in. Enforced per-PR by the same `ci/check_shipped_skill_refs.awk` as the path rule — it takes the ship list via `-v shipped=`, so a skill sitting on disk but absent from `install/skills.list` is still caught. |
| Five checks. Each is deliberately narrow: a gate that cries wolf gets muted, and then it | ||
| is worse than no gate. Two escape hatches, both spelled `repo-only`: | ||
| * in a HEADING -> exempts that section, resetting at the next heading of any level. | ||
| (Not "everything after the marker": cpp_integration.md has a repo-internals section | ||
| in the MIDDLE, and a trailing rule would exempt the rest of the file.) | ||
| * on a LINE -> exempts that line, for one-off mentions in prose. | ||
|
|
| `daslang-live.exe` is a live-reloading application host. It compiles and runs a daScript file, then watches for file changes and hot-reloads the script without restarting the process. It also exposes a REST API for remote control. | ||
|
|
||
| **Binary:** `bin/Release/daslang-live.exe` | ||
| **Binary:** `bin/daslang-live` |
…, and lens rails
Everything the cm2 production twin needs underneath it, landed green before
the kernel itself:
- KqFmt.q8n (= 6): the same q8 weights as gguf-native 34B interleaved blocks
({f16 d; int8 qs[32]}, ONE plane) — a GPU-tier tag, never a disk format.
Schema gains Q8N_BPB; the tier's arena/stack math grows the q8n arm
(single plane, ws = 0, 32-elem blocks via vk_fmt_b32).
- Device + mode: has_coopmat2 probe, DASLLAMA_COOPMAT=cm2 -> mode 4 (guarded
on the extension, downgrades to mm without it), the cm2 device chain via
#77's creator. cm2 stays OPT-IN until it beats mm in the bench — the
fastest-path default is measurement-driven.
- dasllama_layout: moe_gpu_gather_stack_q8n — prepared planes (grp<mr> or
row-major, wbias XOR) -> interleaved 34B blocks; hook chain extended
(GatherStackQ8nFn, register_model_layout arity +1).
- Kernel-access lens: the cm2 tensor intrinsics modeled (coopmatStoreTensor
writes arg 1; coopmatLoadTensor/Decode plain reads) on top of the merged
GaijinEntertainment#3570 analyzer.
Gates: full chain compiles, lint 0 across 5 files, test_vulkan_tier 34/34.
Branch rebased onto master (post-GaijinEntertainment#3570/GaijinEntertainment#3571) with a full C++ rebuild and a
fresh dasVulkan shared_module.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G1Qe2TFnnxaLv4TyQm9Xeh
What
Audited
cmake --installcoverage against the tree and fixed the gaps. Seven of them broke workflows the shipped docs tell users to follow.The worst:
utils/mcp/setup.dashas never been installed, while the installedutils/mcp/README.md(L175-192) and the shippedskills/mcp_tools.md(L73) both document running it. The MCP bootstrap was impossible from a bundle through 0.6.4. Its companionmcp_supervisor.py— whichsetup.daswrites into.mcp.json— was missing too.Root cause of the whole class:
ci/smoke_test_bundle.shcompiled 9 of the 14 installed.dasentry points, andsetup.dassat in the gap, so nothing ever noticed. All 14 are covered now — 12 checks → 17.Ship what was missing
utils/mcp/setup.das+mcp_supervisor.pyutils/mcp/tests/non-.dasfixturesFILES_MATCHING PATTERN "*.das"dropped_fixture_cpp_outline.hand_pretend_root/.../.das_module, both required by the installedtest_tools.das(L2130, L2611)utils/lint/tests/(77 files)examples/daStrudel/sfx_labsounds/*.sfx(27) +.das_packagebatch_drums.das:19,batch_synth.das:23,export_drums.das:12read them viaget_das_root()— shipping the scripts alone left them brokenexamples/graphicsper-example.das_package+.gitignore-project-rootwhoserelease_mainpoints at the shared source one level up; the non-recursive glob dropped the load-bearing manifestsexamples/benchmarks/examples/README.md:184-193, which also links its READMEaot_testing/llvm_tune/perf_lint/style_lintskillstree-sitter-daslang/zed-daslang/install/README.mdpoints users at itCHANGELIST.mdintegration_cpp_23in the standalone recipe23_handle_registry.{cpp,das}shipped with no way to build it;handle_registry.hwas already installedtutorials.mddeliberately stays repo-only — shipping it would drag indocumentation_rst.mdand onward — so the one reference to it (skills/xml.md) is reworded instead.Decouple tutorial data install from
DAS_TUTORIAL_DISABLEDThe install rules for all 79 C/C++ integration tutorial sources lived inside the gated
include(), so "don't build the tutorial executables" silently also meant "don't ship the tutorial sources."release.ymlnever sets the flag, so shipping was fine today — but the coupling was a trap. Verified by flipping the flag: 50 integration-source refs survive in the generated install script.Hygiene
FLEX(utils/dasFsormatter/ds_lexer.lpp)— typo'd dir that does not exist, anddasFormatterhas no.lppat all. Inert only because no target consumed the output path (flex is found on some boxes, so this was not protected byFLEX_FOUND).examples/daspkgused a hardcodedDESTINATIONinstead ofDAS_INSTALL_EXAMPLESDIR, and neither it norexamples/gamesexcludedmodules/or build output — a dev tree would ship daspkg junk.file(STRINGS)oninstall/skills.listnow passesENCODING UTF-8. Without it, non-ASCII bytes act as separators: an em-dash in a comment splits the line and the tail is read as a skill filename, failing the guard with a nonsense path. (Hit this for real while writing the patch.)dasHV tutorial artifact
tutorials/dasHV/_upload_test/_testfile.txtwas committed because the server saves{upload_dir}/_testfile.txt(L279) butcleanup_upload_dirremoved{dir}/testfile.txt(L158, no underscore) — the file survived,remove(dir)failed on a non-empty dir, and it landed in git. Fixed the name, untracked the file, gitignored the run dirs. Also corrected the Zed extension path in both READMEs (zed-daslang/, noteditors/zed/).Durable rules recorded
skills/install_instructions.mdnow carries the shipped-skill closure invariant (a shipped skill may only referenceskills/<other>.mdwhen that other ships; repo-only skills stay off the list and referring skills get reworded) with a copy-paste check script, plus the ASCII-only rule forskills.list.Verification
ci/release_modules.txt) built and installed to a scratch prefix, then diffed against the pre-fix bundle: exactly 134 files added, nothing unintended.ci/smoke_test_bundle.sh: 17/17 passing.DAS_TUTORIAL_DISABLED=ONreconfigure: integration sources still install..das.Known follow-up (not in this PR)
The 33 shipped skills reference ~90 repo-only paths that can never exist in an SDK bundle —
src/*.cpp,tests/**,doc/source/**/*.rst,benchmarks/**,modules/*/src/*.h— plusexamples/{fatman,flatten,telegram/dictation,vulkan},utils/watchdog,utils/dasllama-server. Rewriting those to daslang.io URLs vs. gating the paragraphs vs. accepting them is a product call about whether SDK-facing skills should read repo-internal at all, so it is left out deliberately. The skill→skill half of this class is fixed and guarded here.Separately, the ten
daslang -exeutils (aot,dascov,daspkg,detect-dupe,hygiene,jit,lint,benchctl,mcp,dastest) are built byadd_custom_command, soinstall(TARGETS)cannot reach them and none ship — bundles run them from source. That is by design; this PR only corrects the stale comment in the smoke test that claimed otherwise.Commit 2 — make the SDK self-contained (
9cea6f157)The audit above found the install rules broken. This second commit fixes the other half: shipped skills sent readers to 70 repo paths a bundle never contains. Two problems were tangled there, needing opposite fixes.
Where the skill relies on the content, the content now ships
One source file, as markdown. Sphinx learns to read markdown (
myst-parser==2.0.0, the last line supporting Sphinx 7.2.6) and each.rstbecomes a ~13-line pointer that includes the.md. daslang.io and the SDK then read the same bytes — nothing to drift, no generated artifact to keep in sync.skills/design_philosophy.mdreference/design_philosophy.rstskills/tune.mdreference/tune.rstskills/profiler.mdreference/utils/profiler.rstskills/linq_fold_patterns.mdreference/linq_fold_patterns.rstskills/detect_dupe_reference.mdreference/utils/detect_dupe.rstTwo of those RST pages share a stem with an existing shipped skill, because they are the same topic twice — and they are not the same case.
memory_leak_detection.mdsaid outright that its RST "covers the same material in docs style", so that pointer is reworded and nothing new ships; four of its five references now resolve toskills/profiler.md, inside the bundle.detect_dupe.rstis genuinely fuller than its skill (541 lines, five flag tables), so it ships under a non-colliding name.Breadcrumbs in
json.md/regex.md/das_macros.md("RST companion at…", "generated stdlib reference at…" — two of them namingstdlib/generatedfiles that don't exist in a fresh checkout) point at the published page instead.Where the path is engine internals, the answer is the reverse
src/,tests/,benchmarks/,modules/*/srcare never going into a bundle. So the line says so with arepo-onlytoken and the reader skips it, instead of hunting a path that isn't there. 21 refs marked — two heading retitles cover 7 (cpp_integration's "C++ Codebase Notes",jobque_debugging's "Key files"), and 12 one-off prose mentions are marked inline so the sentence stays with the point it supports.Enforced per-PR by
ci/check_shipped_skill_refs.awk, run fromci/smoke_test_bundle.sh— that'sbuild.yml'sbundle_smokejob, which triggers onpull_request, so no new CI wiring. Smoke test 17 → 18 checks.Exemption is section-scoped and resets at each heading. A trailing-marker rule would leak the exemption through the rest of the file, which is wrong for
cpp_integration.md, whose internals section sits mid-file. Fenced blocks are exempt because they quote tool output verbatim — including a compiler warning that literally prints adoc/sourcepath.Verified, not assumed
sphinx-build -W --keep-going): zero new warnings, six removed, against a 282-line baseline.src/path fails withfile:line; the same line markedrepo-onlypasses; a fenced path is ignored.doc/sourcecitations from shipped skills: 9 → 1, and that one is the fenced compiler warning.Two findings worth recording, both caught the hard way:
(label)=target does not register in Sphinx's std domain when the markdown arrives via.. include:: … :parser:. Page labels therefore live in the.rststub, and two bare:ref:s needed explicit link text once the title moved into the markdown. Each stub says so.file(STRINGS)treats non-ASCII bytes as separators, so an em-dash in aninstall/skills.listcomment splits the line and the tail is read as a filename. Fixed withENCODING UTF-8plus an ASCII-only rule; the guard failing loudly is how it surfaced.Deliberately not in this PR
tests/— 53 refs, 24 of them inaot_testing.md. That class needs sorting into inline-the-snippet (where the code sample is the payload) vs quarantine, and it overlaps the question of splittingaot_testing.md/writing_tests.md, which are mixed-audience files. The awk carries a comment saying to addtests/when it lands.🤖 Generated with Claude Code
https://claude.ai/code/session_01WiXc1jvihNmEnU7DDQidvt