| title | Architecture audit checklist |
|---|---|
| slug | audit |
| summary | Checklist for sweeping origin/main for SOLID and boundary violations. Records findings in the audit log; schedules blockers as new plan files. |
The solid-architecture skill holds the generic audit workflow.
This page is the mdsmith-specific binding. It pins down the audit log path, the plan numbering convention, the lint command that refreshes parent catalogs, and the project's lint budget.
- Audit log location:
docs/development/architecture-audit.md. Created on the first run from the skill checklist's "Initial file" template. audit-from:front-matter field: the SHA the next sweep starts from. Updated at the end of every audit.- Plan directory:
plan/with a numeric prefix (plan/<id>_arch-fix-<slug>.md). The id is the minute-precision UTC creation time,date -u +%y%m%d%H%M; if that id is taken, add one minute. Never allocate "highest prefix plus one" — the allocation contract lives in plan/proto.md. - Plan status sentinel:
🔲for "not started" (see plan/proto.md). - Lint command after recording: run
mdsmith fix .from the workspace root so the audit-log entry refreshes in the parent catalogs in CLAUDE.md, AGENTS.md, PLAN.md, and.github/copilot-instructions.md. - Line-length budget for log
entries: 80 characters outside code
blocks, tables, and URLs (the project
default in
.mdsmith.yml). - Readability budget: bullet lists beat dense paragraphs for the per-finding "suggested fix". Single sentences over ~30 words trip MDS023 / MDS024 on the audit log.
---
title: Architecture audit log
summary: >-
Running log of SOLID and clean-
architecture findings on origin/main.
The solid-architecture skill (audit
mode) appends here; blockers are also
filed as plans.
audit-from: <commit SHA one month ago>
---
# Architecture audit log
This file is maintained by the
solid-architecture skill in audit mode.
## Audit YYYY-MM-DD (range:
<from-sha>..<to-sha>)
### blockers
### tax
### nice-to-haveIf the one-month-back lookup returns empty on this repo, fall back to the root commit:
git rev-list --max-parents=0 origin/mainUse the first SHA from that output as the baseline. (At the time of writing, the mdsmith repo is younger than a month, so every audit so far has used this fallback.)
Follow the steps in the skill's audit checklist exactly. The skill describes the generic workflow:
- Refresh the checkpoint (with the shell-variable warnings the skill spells out).
- Walk the language-level layering checks — Go and TypeScript — using Go patterns and TypeScript patterns on this repo.
- Walk the cross-system contract checks against cross-system contracts.
- Apply the severity rubric.
- Append findings to the audit log
under a new
## Audit YYYY-MM-DDheading. - Group blockers by the structural fix they share into one plan each.
- Tell the user what was found and what was scheduled.
Architecture audits also check test coverage. The Test pyramid doc is the source of truth; the language pages (Go, TypeScript) include it and add file-pattern bindings. The mdsmith-specific knobs the audit needs are below.
- Unit-test location:
xxx_test.gonext toxxx.gofor Go;xxx.test.tsnext toxxx.tsfor the VS Code extension. - Function-coverage rule: every
Go and TypeScript production
function — both exported and
unexported — has a dedicated test
by name (
TestFoofor Go packagefunc Foo,TestReceiver_Foofor a method onReceiver; adescribe("foo")block with one or moretest(…)cases imported frombun:testfor TSfoo). Test files (*_test.go,*.test.ts) and test-only helpers are out of scope — the audit walks production sources only. Generated files (*_gen.go,*.d.ts,dist/) and trivial accessors with no branch are exempt; see Test pyramid §"Exemptions". - Contract tests for Go in this
repo live under
internal/integration/rather than alongside the port-package they pin. Examples:internal/integration/rule_boundaries_test.go,internal/integration/directive_examples_test.go. - Integration test location:
internal/integration/for Go. TypeScript integration tests sit next to the command module they exercise. - E2E test location: under
cmd/mdsmith/for Go, defined by behaviour (the test spawns the built binary and drives it over stdio, exit code, or signals). Three filename shapes appear in the repo, all e2e:e2e_prefix (e2e_test.go,e2e_backlinks_test.go),_e2e_suffix (kinds_e2e_test.go,list_e2e_test.go,explain_e2e_test.go), and topic-named LSP subprocess tests (lsp_test.go,lsp_hover_test.go, …). Demo tapes underdemo/are also e2e. The VS Code extension host runs are e2e for the TypeScript side. - Severity for missing unit
test:
taxby default;blockerif the function is on a public surface (arule.Rulemethod, an LSP capability handler, a CLI subcommand entry, an exported VS Code command).
These show up enough that they deserve explicit mention here:
- A rule package importing another
rule package — always a DIP
blocker. Helpers belong in
internal/mdtextorinternal/rules/astutil. cmd/mdsmith/main.gopast ~1000 lines — handler bodies have crept in; relocate tointernal/engineor a per-subcommand file.internal/lsp/server.goorsymbols.gopast ~1000 lines — split along the dispatch groups.- A
.mdsmith.ymlfield reachable from only one rule — push it into that rule's settings struct. - A new public method on
internal/engineadded to satisfy one LSP capability — consider consuming an existing engine output instead. - A test that imports
internal/engineto test a rule — push it to a fixture under the rule'sgood/orbad/directory. - A Go function with no matching
test symbol in a sibling
*_test.go—TestFoofor a package functionfunc Foo,TestReceiver_Foo(orTestReceiver_Foo_Variant) for a method onReceiver. Test debt; severity per the rule above. - A TypeScript function not
covered by a
describe("name", () => { test(…) })block (withdescribe/testimported frombun:test) in a sibling*.test.ts— same rule for the extension. - A test under
internal/integration/that exercises a single function — pyramid is inverted; push the assertion down to a unit test in the function's own package. - A test that spawns the
mdsmithbinary as a subprocess to assert behaviour reachable without it — pyramid is inverted regardless of the filename shape; e2e tests build and run the binary, reserve them for behaviour that needs the full process boundary.
- Files under
testdata/andinternal/rules/MDS###-<rule-name>/{good,bad}/are fixtures; their architecture is by design. - Generated section bodies (between
<?directive?>markers) are auto-produced; review the directive parameters, not the body. - Comments-only changes do not require an audit entry unless they document a contract that has changed.
- Vendored or generated Go code
(
*_gen.go, code underinternal/…/gen) is excluded.