PHP was the one language with real code in two shapes here and no skill: a
Composer library held at PHPStan level max, and a plain PHP-FPM application
behind nginx with no framework. The rules come from reading both rather than
from general PHP advice, so each one names the failure it prevents.
The two halves differ enough to be separate sections. A library requires PSR
interfaces and ships no implementation; an application's rules are about
escaping, keeping the document root unwritable, atomic writes and sessions.
Everything in §1-§8 applies to both.
Three findings are worth the space they take because they were each paid for
once already: `json_encode` with JSON_UNESCAPED_SLASHES into an inline
<script> is an XSS hole, a web user that cannot write its own cache fails
silently on every request, and inside the dev container the host's own `php`
bridge shadows the real interpreter so every vendor/bin tool dies naming
distrobox.
docs(python): cover MCP servers, Red cogs and HA components, and correct three
rules the owner's own code contradicts
The skill described a toolchain and was silent on the four things most of this
Python actually is. Three of its rules are also wrong in context, and the code
is right: getLogger(__name__) puts a cog outside the red.* tree where Red's log
controls apply; TaskGroup's cancel-on-first-error is the wrong default for
fan-out over N providers, where the real pattern is a semaphore plus
gather(return_exceptions=True); and the gate runs locally and through
pre-commit, not through CI, which never runs under this account.
Also: ruff ALL-minus-documented-ignores is the preferred shape rather than the
explicit select list, lockfiles split by artifact type, and bare `python` and
bare `pip` are different interpreters on this host.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A value with rules of its own — a URL, a path, a closed set, an identifier —
gets a type of its own. Passing it as a bare string discards those rules at the
first function boundary and leaves every consumer re-deriving them.
Added as a subsection of Architecture Preferences, with a table mapping the
common cases to the type to reach for in any language, the reasoning, and the
boundary rule: parse once at the edge, keep the type inward, serialize back only
where the wire actually demands a string. Notes the counter-case, so this is not
read as a mandate to wrap every string.
python.md gains the concrete choices: yarl.URL (already present wherever aiohttp
is), pathlib, StrEnum, and NewType for non-interchangeable identifiers.
Verified with `ruff rule PLR0915`: it is `too-many-statements` (default 50),
not a line-length rule. Ruff has no line-based function-length rule at all.
python.md now says so and points both limits at a pytest case; coding-dev.md
gains the general distinction between a real length lint and a proxy.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A shell check only runs where that script runs. A test travels with the repo,
needs no extra tooling, and fails with a message naming the offending files.
Enforcement is now a preference order: native linter rule > test > build
script as fallback, with a worked example and a note on why a per-compile
build hook usually is not worth the incremental-build cost.
Propagated per language: rust (clippy has no file-length lint -> workspace
root test), js-typescript (ESLint max-lines covers both natively, no test
needed), go/python/csharp (linter for functions, test for files), bash (don't
reimplement in the gate what a test can assert).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- all nine files: trailing "Related" sections removed, their unique links
inlined where the topic actually arises (FFI boundary -> c-cpp, embedded
frontend -> js-typescript, build scripts -> bash, etc.)
- README conventions: rule 2 mandated a Related Skills section, which now
contradicts practice — replaced with inline-linking and one-home-per-fact
rules. The <repo>/<rel path> rule was appended after the wrong section
last commit; moved into the list where it belongs.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All cross-skill links now spell out the repository: skills-public/foo.md,
skills-private/bar.md. These resolve from the shared parent directory, so one
spelling works from either repo and from code-languages/ subdirectories —
replacing the previous mix of ./, ../ and absolute file:// URLs. Link labels
normalised to match. Convention added to the README conventions list.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Generic coding rules and preferences distilled from existing agent rule
files, project AGENTS.md/.rules, and saved memories:
- strictness maximal; suppressions must be reported to the user
- never filter build/lint/test output through grep/tail/head
- reuse > fork > self-implement; generic code becomes its own package
- 1000-line file / 100-line function limits, split by concern
- regression test every fixed bug; never test against real user data
- events over polling; scope discipline; honest reporting
Per-language: rust, js-typescript, bash, python, go, csharp-dotnet, c-cpp.
Each extends coding-dev.md rather than repeating it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>