# coding.sgit.ai — full text Site version: v0.2.0. Every page and every source document of https://coding.sgit.ai/ in one file, so an agent can read the whole thing in a single fetch. GENERATED — assembled by admin/build/gen_llms_full.py from llms.txt, index.md and briefs/*.md, and re-checked in CI. It cannot say anything the site does not. Structure of this file: PART 1 the index (llms.txt), for orientation and the stable-URL promises PART 2 the front page in full (index.md) PART 3 the 13 source documents this site is written from, verbatim All content CC BY 4.0 — Dinis Cruz, with AI co-authorship (Claude, Anthropic). ============================================================================== PART 1 — THE INDEX (source: /llms.txt) ============================================================================== # coding.sgit.ai — how software actually gets written here > The sgit.ai network's site about coding style: five languages (Python, JavaScript, HTML, > CSS, Bash) as they are actually written across 217,266 lines. Every convention was derived > by COUNTING the code, not from documentation. Where a documented rule and the code > disagree, both are published with the numbers — including the numbers that do not flatter. Site version: v0.2.0 (25 August 2026). Published by the sgit project, which builds the tools and wrote the code this site measures — participant disclosure at /about/participant.html. All site content CC BY 4.0. The code quoted throughout is Apache-2.0 and carries its own notice; Type_Safe, Safe_Str and the constrained-primitive pattern come from osbot-utils, Apache-2.0, under the owasp-sbot GitHub organisation. ## The headline 31 documented rules. 0 linters, 0 formatters, 0 type-checkers anywhere in the estate. 4 tests/ci/ structural guards are the entire automated enforcement surface, and a 5th has never worked: its regex is `sgraph_ai_service_playwright[^_]`, and `[^_]` cannot match the real package `sgraph_ai_service_playwright__cli`. 0 files matched; 228 real imports across 69 files. Measured against 992 class-defining files: banners 100%, no-docstrings 99.7%, empty __init__.py 99%, one-class-per-file 90%, no-underscore-private 91% (97 violations). Import alignment is 39% and is not a documented rule at all. And the estate's prose rule that "all documents are em-dash-free" is broken 248 times across the 11 documents that state it — not one file has zero. This site follows the practice rather than the stated rule, and says so. None of the 31 numbered rules carries a passing CI guard. The four working guards each encode an INCIDENT rather than a rule, so the written rule set and the tested rule set do not currently overlap at all. ## Properties agents may rely on - Every source document is fetchable at a stable constructed URL: /briefs/. 13 of them, 12,983 words, published in full. - /llms-full.txt is this site in one fetch: the index, the front page and every source document, in the pack's own reading order. GENERATED from those sources and re-checked in CI, so it cannot say anything the site does not. - /briefs/conventions__machine-readable.json is the SOURCE of every number on this site, not a copy of them. admin/build/gen_inline.py writes each figure into each page from that file and CI fails the release if one has drifted. - Every code example is written into its page by the same generator, from the source document it was quoted in, carrying its real repository path and its own Apache-2.0 notice. A snippet on this site cannot be something nobody wrote. - /data/rules.json is the machine-readable rule set: 31 rules plus 4 testing non-negotiables, each with its measured compliance, an enforcement badge, and a flag saying whether the text is quoted verbatim or paraphrased. /rules/ is generated from it. - /data/documents.json is the machine-readable document index. /documents/ is generated from it. - /sitemap.xml is generated from the tree, so it cannot omit a page somebody forgot to add. - The version in /admin/build/version.txt agrees with the badge on every page, the release history table, this file, /llms-full.txt and /index.md — CI fails the release otherwise. ## The pages - /index.html — the thesis in one page: the hook, the four decisions everything follows from, the five languages, and what this site does not claim. Markdown twin: /index.md - /style/index.html — what is shared across all five languages. One idea per file, banners and their four forms, the argument that alignment is a machine-readability decision, and single source of truth enforced by structure rather than by asking. - /python/index.html — the deepest language. The complete eleven-line example with nine conventions in it, the naming families, Type_Safe, constrained primitives, layout, testing, the responsibility boundaries, and the osbot-* dependencies. - /javascript/index.html — native web components, no framework, no build step. The three-file triplet, static jsUrl = import.meta.url, the versioned CDN path scheme, the SgComponent contract, the sp-cli: legacy event namespace, and the four inconsistencies to settle. - /html/index.html — fragments not documents, 2-space indent, ARIA, data-* as the behaviour hook, injected chrome, and the markdown twin. - /css/index.html — per-block value alignment, design tokens and their three competing prefixes, theming, and why shadow DOM makes BEM unnecessary. - /bash/index.html — 5 .sh files in 217,266 lines. The Section__* generated-shell pattern, its seven-part anatomy, the trade it makes, and the two cheap mitigations that do not exist. - /rules/index.html — all 31 rules plus the 4 testing non-negotiables, each with its measured compliance and an enforcement badge, plus the 14 conventions that are consistent in the code and are not rules anywhere. GENERATED from /data/rules.json. - /enforce/index.html — the configs, shipped as files: /enforce/ruff.toml, /enforce/eslint.config.js, /enforce/stylelint.config.js, /enforce/test_house_style.py, /enforce/test_rendered_shell.py, /enforce/check_components.py, /enforce/check_markup.py. Plus an honest table of what ruff, eslint and stylelint genuinely cannot express and why — including the correction that ruff CANNOT encode "no docstrings" (pydocstyle requires them and there is no inverse rule), which the brief assumed it could. - /shipped/index.html — what is NOT enforced. Nothing is enforced by tooling; one guard never worked; two more are claimed and unlisted; four of five languages are undocumented; the bad numbers; and what this site itself cannot do. - /for-agents/index.html — the conventions that only make sense once an LLM is a primary reader and writer. Published as a position with the evidence attached, not as a finding. - /open-questions/index.html — 8 open questions, 6 tensions, 7 loose ends, 7 unwritten items. - /documents/index.html — the 13 source documents, published in full, with a section on exactly what was redacted and what was deliberately kept. - /admin/index.html — how this site is built: the pipeline, the gate, the tagger, the generators. /admin/versions.html — the release history. /admin/comms.html — tasks and requests, including R2, the build-time extraction this site does not do. - /network/index.html — the sibling sites and the boundaries between them. - /about/participant.html — who publishes this and how it is written. ## What is NOT here, and should be - Build-time extraction from the repository. The commissioning brief's house rule is that every count and example is extracted from the code at build time with a commit reference. This repository holds the website, not the 217,266 lines it describes, so every number is written in from a DATED survey (2026-08-24) instead. The counts cannot drift from the survey; they can and will drift from the code. Tracked as R2 in /admin/comms.html. - Rules for JavaScript, CSS, HTML and Bash. All 31 documented rules are Python and process. The 14 conventions listed at /rules/#unwritten are candidates and none of them is a rule yet. - Any resolution of the 8 open questions. They are published unresolved on purpose. ## Redaction Two of the 13 source documents carry the pack's own do-not-publish list, which names the values it forbids. In those two files only, an AWS account id, four live internal hostnames and four named live stack FQDNs are replaced with [redacted]; the occurrence counts are kept and each change is marked in place. dev.tools.sgraph.ai is deliberately NOT redacted, because it appears inside the code examples and a component example without its import URL teaches nothing — see open question Q4. Full account at /documents/index.html#redaction. ## Related - https://sgit.ai — the parent project and the network index - https://open-source.sgit.ai — the other half of the /for-agents/ argument - https://sg-compute.sgit.ai — the platform; the richest source of the examples quoted here - https://llms.sgit.ai · https://standards.sgit.ai · https://issues-fs.sgit.ai - https://graphs.sgit.ai · https://wardley-maps.sgit.ai · https://risks.sgit.ai - https://nhi.sgit.ai · https://pki.sgit.ai ============================================================================== PART 2 — THE FRONT PAGE (source: /index.md) ============================================================================== # coding.sgit.ai — the style guide that measured itself > Five languages — Python, JavaScript, HTML, CSS, Bash — as they are actually written across > 217,266 lines of code. Every convention here was **derived by counting**, not from > documentation, and where a documented rule and the code disagree, both are published with > the numbers. *Source: · site v0.2.0 · markdown twin of the front page.* --- ## 31 documented rules. 0 linters. 4 guards, and 1 of them never worked. This estate has a written style guide, which is more than most projects have. It lives in `.claude/CLAUDE.md` — an agent instruction file, not a published standard — and until the survey behind this site, **nobody had ever measured whether the code obeys it**. ``` # measured against 992 class-defining files rule 7 ═══ banner on every file 100% 992 / 992 rule 8 no docstrings, ever 99.7% 3 violations rule 22 __init__.py stays empty 99% 299 / 302 rule 21 one class per file 90% 187 / 208 sampled rule 9 no _ prefix on private methods 91% 97 violations import alignment 39% 321 / 817 # not a rule at all # enforcement surface, entire: tests/ci/ 4 structural guards + 1 that has never matched anything ``` The last line is the one worth reading twice. The guard is supposed to fail the build if the new tree imports the legacy one; its regex requires a non-underscore character after a package stem that has two, so it matched nothing and passed. There are 228 real imports across 69 files. [A guard that passes because it cannot match what it guards against](shipped/index.html#broken-guard). ## The four decisions everything else follows from These are not style preferences with a rationale bolted on afterwards. They are four choices that produce each other, in a codebase where **61% of commits were written by an agent** and a human still has to review the result. - **Runtime validation, not static analysis.** There is no type-checker anywhere in the estate. `Type_Safe` from `osbot-utils` validates at construction instead, so a value that exists is a value that is valid — and a generated mistake fails at the point of the mistake rather than in a checking pass nobody runs. [How it works](python/index.html#type-safe). - **The type is the validation.** Zero raw primitives. `Safe_Str__SSM__Path`, `Safe_Int__Port`, `Safe_Str__Node__Name` — 27 constrained types in one directory. Naming a type is how a domain concept gets recorded. [The pattern](python/index.html#primitives). - **One idea per file, and the filename says which.** The filename is the class name, `__init__.py` stays empty, nothing is re-exported, and there is exactly one import path to anything — so a symbol is locatable by constructing a path, with no index and no grep. [Across all five languages](style/index.html#one-idea). - **A model is a primary reader.** Runtime validation, constrained primitives, no re-exports, banners instead of docstrings, single-owner responsibility boundaries and the markdown twin all read as one coherent design once you accept that. The most original page here, and the least verifiable. [The argument](for-agents/index.html). ## The five languages One is documented. Four are not, and reconstructing them by counting is most of what the survey behind this site did. - **[Python](python/index.html)** — 3,999 files, 217,266 lines. Double-underscore naming families (`Schema__` 614, `Safe_Str__` 290, `Enum__` 185), one class per file, `═══` banners, and column-aligned assignments. Nine conventions visible in one eleven-line file. - **[JavaScript](javascript/index.html)** — 50 files, no framework and no build step. Native web components, a three-file triplet per component, a self-locating base class, and a versioned CDN path instead of a lockfile. Written down nowhere until now. - **[CSS](css/index.html)** — 38 files. Alignment carried into property values, every colour a token, and plain semantic class names because shadow DOM removes the problem BEM exists to solve. - **[HTML](html/index.html)** — 37 files. Fragments rather than documents, 2-space indent, ARIA on every control, and one rule worth its own line: classes are for styling, `data-*` is for behaviour, and the two never mix. - **[Bash](bash/index.html)** — 5 `.sh` files in 217,266 lines. Shell is not written here, it is generated from 15 typed Python classes that each render a fragment. A real trade, argued rather than reported. ## What this site does not claim **Nothing here is enforced by tooling.** Compliance of 100%, 99.7% and 99% is achieved entirely by discipline, which is impressive and exactly as fragile as it sounds. Four of the five languages have no documented rules at all. Import alignment is 39%. Two CI guards are claimed in the rule set and do not appear in the rule set's own table of guards. And the most interesting page here is a position with the evidence attached, not a finding. There is also one thing this site was commissioned to do and does not: **extract its counts from the repository at build time**. This repository holds the website, not the code it describes, so every number here is written in from a **dated survey** — 2026-08-24 — by a generator, with CI failing the release if a published number has drifted from it. That closes the drift-within-the-site problem and leaves the freshness problem open, and it is tracked as request R2. - [What is not enforced](shipped/index.html) — the bad numbers, in one place. - [Open questions and tensions](open-questions/index.html) — 8 questions, 6 tensions, 7 loose ends. - [Enforcement](enforce/index.html) — the ruff, eslint and stylelint configs, shipped as files, with an honest account of the seven rules no linter can express. ## Where this sits - [The source documents](documents/index.html) — all 13, 12,983 words, published in full. Two of them carry the pack's own do-not-publish list, and are published with that list redacted. - [open-source.sgit.ai](https://open-source.sgit.ai) — the other half of the argument. That site has the position; this one has the artefact. - [The sibling sites](network/index.html) — what each one owns and where the boundaries fall. - [Who publishes this](about/participant.html) — the sgit project publishes this site and wrote the code it measures. Stated on the way in rather than in a footnote. --- *All content CC BY 4.0 — Dinis Cruz, with AI co-authorship (Claude, Anthropic). The code quoted throughout is Apache-2.0 and carries its own notice; `Type_Safe`, `Safe_Str` and the constrained-primitive pattern come from `osbot-utils` under the `owasp-sbot` organisation.* ============================================================================== PART 3 — THE 13 SOURCE DOCUMENTS ============================================================================== Each is also fetchable on its own at /briefs/, in the pack's own reading order rather than alphabetically. ============================================================================== source: /briefs/README.md ============================================================================== # coding.sgit.ai — brief pack **For:** the agent commissioned to build `coding.sgit.ai` **From:** Dinis Cruz, via the SG/Send Librarian **Version:** v0.33.62 · 24 August 2026 **Licence:** CC BY 4.0 — the code quoted throughout is **Apache-2.0**. See `LICENSE.md`. --- ## What this is The coding patterns and formatting across the five languages you work in: **Python, JavaScript, HTML, CSS, Bash.** Every convention here was **derived from the code by counting**, not from documentation — and where a documented rule and the code disagree, both are reported with the numbers. --- ## The headline **You already have a written style guide.** `.claude/CLAUDE.md` carries **31 numbered rules** plus 4 non-negotiable testing rules. Measured against 992 class-defining files: | Rule | Compliance | |---|---| | `═══` header on every file | **100%** (992/992) | | No docstrings, ever | **99.7%** (3 violations) | | `__init__.py` stays empty | **99%** (299/302) | | No `_` prefix on private methods | **91%** (97 violations) | **The site's job is not to invent a style guide — it is to publish the one that exists, with the measurements, and make it enforceable.** --- ## Read in this order | File | Words | What it does | |---|---:|---| | **`00__BRIEF.md`** | 1.2k | **Start here.** The headline, the five languages in a paragraph each, what makes the style unusual, the numbers, the build order | | **`01__python.md`** | 1.5k | The deepest language. The complete 11-line example, naming families, `Type_Safe`, constrained primitives, alignment, testing, responsibility boundaries | | **`06__the-rules-and-compliance.md`** | 1.1k | **The page that makes the site useful** — all 31 rules with measured compliance, and the guard that never worked | | `02__javascript.md` | 1.2k | The framework-free component system, the three-file triplet, the versioned CDN — **undocumented anywhere** | | `03__html-and-css.md` | 0.9k | Alignment in CSS, design tokens, `data-*` as the behaviour hook, why shadow DOM makes BEM unnecessary | | `04__bash-and-generated-shell.md` | 0.9k | **Five `.sh` files in 217k LOC** — shell is generated from 15 typed `Section__*` classes | | **`05__cross-cutting.md`** | 1.3k | What's shared across all five, and **`/for-agents/`** — the most original page available | | `07__site-architecture-and-boundaries.md` | 1.0k | Page by page, licensing, redaction, network boundaries | | `08__gaps-and-open-questions.md` | 1.2k | An 8-item enforcement fix list, 7 build-fresh items, 7 open questions, 6 tensions | | `09__source-manifest.csv` | 20 rows | Every source, tiered 0–3. **Every path verified on disk** | | `conventions__machine-readable.json` | — | Every count and rule as structured data — for generating the site's pages | | `LICENSE.md` | — | CC BY 4.0, the Apache-2.0 distinction, and the redaction list | --- ## The four things worth knowing before you write **1. There is no linter, formatter or type-checker anywhere in the estate.** No mypy, ruff, flake8, black, isort, tox — no config at all. Type safety is enforced *at runtime* by `Type_Safe`, which is a real and defensible choice. The four `tests/ci/` structural guards are the entire automated enforcement surface — **and one of them has never worked**: `test_no_legacy_imports.py` uses `sgraph_ai_service_playwright[^_]`, which cannot match the real double-underscore package. Verified: **0 files matched, 228 real imports across 69 files.** **2. Four of the five languages have zero documented rules.** All 31 are Python and process. JavaScript, CSS, HTML and Bash have consistent, discoverable conventions that nobody has written down — reconstructing them by counting is most of what `02__`–`04__` did. **3. Alignment is the estate's most visible convention and its least explained.** Schema attribute colons are **100% aligned**; CSS property values are aligned per block; imports are only **39%**. `05__` §3 makes the argument that alignment is a *machine-readability* decision in a codebase **61% written by an agent** — that is a claim, it is falsifiable, and it should be published as a position with the evidence attached. **4. Bash barely exists.** Five `.sh` files in 217,266 lines. Shell is **generated** from 15 `Section__*` Python classes, each with a `TEMPLATE` and a `render()`. The trade — testable parameters and no quoting hell, against no `shellcheck` and no directly-runnable script — is worth arguing rather than just reporting. Both mitigations are cheap and neither exists yet. --- ## The most original page available `/for-agents/` — `05__` §5. Several conventions only make sense once you accept that an LLM is a primary reader and writer: runtime validation catches a generated mistake at the point of the mistake · constrained primitives encode the domain in the type name · one class per file with filename = class name means a model can locate any symbol by path construction alone · fully-qualified imports with no re-exports means there is exactly one import path to invent · explicit single-owner responsibility rules stop a generator putting a call in a reasonable-looking wrong place · and the markdown twin exists so *"a traversing agent never has to parse HTML."* There is even direct evidence in the filenames: `library/dependencies/osbot-utils/type_safe/v3.1.1__**for_llms**__type_safe__testing_guidance.md`. This connects straight to `open-source.sgit.ai` — that site has the argument, this one has the artefact. --- ## House pattern Copy `pki.sgit.ai`, add the `/llms-full.txt` it lacks, and add one rule specific to this site: > **Every code example and every count is extracted from the repo at build time, with a path and a commit reference.** A style guide whose examples have drifted from the code is worse than no style guide. --- This file is released under the Creative Commons Attribution 4.0 International licence (CC BY 4.0). ============================================================================== source: /briefs/00__BRIEF.md ============================================================================== # 00 — The Brief: `coding.sgit.ai` **Version** v0.33.62 · 24 August 2026 **From** Dinis Cruz, via the SG/Send Librarian **To** the agent commissioned to build `coding.sgit.ai` **Licence** CC BY 4.0 --- ## 1. The commission > *"focused on coding, which will go at `coding.sgit.ai` and I can use to capture all the coding patterns and formatting across the main languages we work on: **python, javascript, html, css, bash**."* All five are covered. Every convention in this pack was **derived from the code by counting**, not from documentation — and where a documented rule and the code disagree, both are reported with the numbers. --- ## 2. The headline: you already have a written style guide, and the code mostly obeys it `.claude/CLAUDE.md` in the sg-playwright repo carries **31 numbered rules** across Code Patterns, Security, AWS Naming, Responsibility Boundaries, Class/File Naming and Testing. That is far more than most projects have, and it is not aspirational — measured against 992 class-defining files in the new tree: | Rule | Compliance | |---|---| | **7 — `═══` 80-char header on every file** | **100%** (992 / 992) | | **8 — inline comments only, no docstrings ever** | **99.7%** (3 violations) | | **22 — `__init__.py` stays empty** | **99%** (299 / 302) | | **9 — no underscore prefix for private methods** | **91%** (97 violations) | | **1 — all classes extend `Type_Safe`** | see §4 — the raw number understates it | **The site's job is not to invent a style guide. It is to publish the one that exists, with the measurements, and to make it enforceable.** --- ## 3. The five languages, in one paragraph each **Python** — 217,266 lines, and the most distinctive style in the estate. Double-underscore class names in families (`Schema__` 614 files, `Safe_Str__` 290, `Enum__` 185, `Cli__` 82, `Routes__` 59), **one class per file, filename identical to the class name**, `Type_Safe` runtime validation instead of static typing, constrained primitive types instead of boundary validation, `═══` banner headers, and **column-aligned assignments**. `01__`. **JavaScript** — 50 files, and the pattern is **native web components with no framework and no build step**: 41 `customElements.define`, ESM imports from a **versioned CDN** (`dev.tools.sgraph.ai/components//v1/v1.0/v1.0.0/…`), a shared `SgComponent` base, and a **three-file component triplet** (`.js` / `.html` / `.css`). 4-space indent, single quotes, **no semicolons**. `02__`. **HTML** — semantic elements, ARIA on every interactive control, `data-*` as the behaviour hook, **2-space indent** (deliberately different from JS and CSS), and the markdown-twin convention where every URL is also available as `.md`. `03__`. **CSS** — **the same alignment discipline as Python, applied to property values.** Design tokens as custom properties served from the versioned CDN (`sg-tokens.css`), `:host` scoping, shadow DOM. `03__`. **Bash** — and this is the surprise: **there are only 5 `.sh` files in a 217,000-line repo.** Shell is not written, it is **generated** from 15 typed `Section__*` Python classes that each render a fragment. `04__`. --- ## 4. The three things that make this style unusual **(a) Runtime type safety instead of static analysis.** There is **no linter, no formatter and no type-checker anywhere in the estate** — no mypy, ruff, flake8, black, isort or tox config. Instead, `Type_Safe` from `osbot-utils` validates at construction. Of 1,034 classes in the new tree: 506 extend `Type_Safe` directly, plus `Type_Safe__List` (44), `Fast_API__Routes` (46) and `Schema__Step__Base` (25) which are themselves descendants — and 78 `Safe_Str` + 13 `Safe_Int` + 6 `Safe_UInt` primitives, 169 `TestCase`, and 77 enums. **Excluding tests and enums, essentially every class is in the `Type_Safe` lineage.** The rule holds; the naive percentage does not show it. **(b) Constrained primitives instead of validation.** Rule 2 is *"zero raw primitives — no `str`, `int`, `float`, `list`, `dict` as attributes."* The estate has 27 hand-written primitive types in `sg_compute/primitives/` alone, each a regex-constrained subclass. `Safe_Str__IP__Address`, `Safe_Str__Node__Name`, `Safe_Int__Port`, `Safe_Str__SSM__Path`. **The type is the validation**, so a value that exists is a value that is valid, everywhere, forever. **(c) Alignment as a first-class convention, across languages.** Schema attribute annotations are **100% colon-aligned** (46 of 46 multi-attribute files). CSS property values are aligned to a column. Trailing comments are aligned. This is unusual, it is deliberate, and — see `05__` §3 — there is a good argument that it is a **machine-readability** decision rather than an aesthetic one. --- ## 5. The honesty constraint `/shipped/` for a coding-standards site means saying what is *not* enforced: - **Nothing is enforced by tooling.** No linter, no formatter, no type-checker, no pre-commit hook. The four `tests/ci/` structural guards are the entire automated enforcement surface — **and one of them has never worked** (`06__` §4). - **Import alignment is only 39% consistent** (321 of 817 files with two or more `from X import Y` lines are aligned to a single column). Attribute alignment is 100%; import alignment is not. - **Rule 9 has 97 violations** in the new tree alone, and the JavaScript uses `_private` methods as a matter of course — so the rule is either Python-only or widely ignored, and the document does not say which. - **The documented rules live in `.claude/CLAUDE.md`**, which is an agent instruction file, not a published standard. **There is no human-readable style guide anywhere.** That is what this site is for. - **No JS, CSS, HTML or Bash conventions are documented at all.** All 31 rules are about Python and process. The other four languages have consistent, discoverable conventions that nobody has ever written down. --- ## 6. The numbers | | | |---|---| | **Python** | 3,999 files · 217,266 LOC · 3,871 filenames contain `__` · 1,034 classes in the new tree | | **Naming families** | `Schema__` 614 · `Safe_Str__` 290 · `Enum__` 185 · `Cli__` 82 · `Routes__` 59 · `Safe_Int__` 18 · `Section__` 15 · `Fast_API__` 12 | | **Suffix families** | `__Builder` 97 · `__Helper` 86 · `__Client` 77 · `__Service` 46 · `__Mapper` 39 · `__Detector` 23 · `__Loader` 17 · `__Registry` 14 · `__Writer` 14 | | **One class per file** | **187 of 208** sampled (90%) | | **Banners** | 3,120 of 3,999 files · **100%** of class-defining files in the new tree | | **JavaScript** | 50 files · 41 `customElements.define` · 6 `attachShadow` · 48 `type="module"` · **single quotes 4,006 vs double 400** | | **CSS / HTML** | 38 CSS · 37 HTML · design tokens from a versioned CDN | | **Bash** | **5 `.sh` files** · **15 `Section__*` shell-generating classes** | | **Enforcement** | **0 linters** · 4 CI structural guards · **1 of the 4 has never worked** | | **This pack** | 9 documents · manifest of **20 rows**, every path verified on disk · the conventions as machine-readable JSON | --- ## 7. Build order 1. **`/python/`** — the deepest and the most distinctive. `01__`. 2. **`/rules/`** — the 31 documented rules, with measured compliance beside each. `06__`. **This is the page that makes the site useful rather than decorative**, because it tells a reader which rules are real. 3. **`/javascript/` and `/components/`** — the framework-free web-component pattern and the versioned CDN. Nobody has written this down and it is genuinely original. `02__`. 4. **`/css/` and `/html/`** — `03__`. 5. **`/bash/`** — the generated-shell story. `04__`. 6. **`/for-agents/`** — `05__` §3. The conventions chosen because an LLM reads and writes this code. The most original page available. 7. **`/enforce/`** — the linter configs that would encode the rules, per language. `08__` §1 has the list; it is a day's work and it converts a description into a standard. Publish the build order unresolved with `08__`'s open questions and tensions visible. --- This document is released under the Creative Commons Attribution 4.0 International licence (CC BY 4.0). ============================================================================== source: /briefs/01__python.md ============================================================================== # 01 — Python 217,266 lines across 3,999 files. The most distinctive style in the estate, and the one with a written rule set behind it. --- ## 1. The complete example — everything in eleven lines `sg_compute/catalog/schemas/Schema__Caller__IP.py`, verbatim and entire: ```python # ═══════════════════════════════════════════════════════════════════════════════ # SG/Compute — Schema__Caller__IP # Response schema for GET /catalog/caller-ip. # ═══════════════════════════════════════════════════════════════════════════════ from osbot_utils.type_safe.Type_Safe import Type_Safe from sg_compute.primitives.Safe_Str__IP__Address import Safe_Str__IP__Address class Schema__Caller__IP(Type_Safe): ip : Safe_Str__IP__Address = Safe_Str__IP__Address() ``` Nine conventions are visible in that file, and the whole style follows from them: 1. **A `═══` banner header** — product name, class name, one line of purpose 2. **The filename is the class name.** `Schema__Caller__IP.py` → `class Schema__Caller__IP` 3. **One class per file** 4. **Fully-qualified imports** from the per-class path — never a package re-export 5. **`import` keywords aligned to a column** 6. **`Type_Safe` as the base class** 7. **A constrained primitive** (`Safe_Str__IP__Address`) rather than `str` 8. **The annotation colon aligned**, with an instance as the default 9. **No docstring.** The banner does that job --- ## 2. Naming ### Prefix families — what the class *is* | Prefix | Files | Meaning | |---|---:|---| | `Schema__` | **614** | Pure data. **No methods** (rule 4) | | `Safe_Str__` | **290** | A regex-constrained string type | | `Enum__` | **185** | A fixed value set. **Never a `Literal`** (rule 3) | | `Cli__` | 82 | A Typer command group | | `Routes__` | 59 | A FastAPI route class. **No logic** (rule 19) | | `Safe_Int__` | 18 | A bounded integer type | | `Section__` | 15 | A shell fragment generator — see `04__` | | `Fast_API__` | 12 | An app assembly | ### Suffix families — what the class *does* `__Builder` 97 · `__Helper` 86 · `__Client` 77 · `__Service` 46 · `__Mapper` 39 · `__Detector` 23 · `__Loader` 17 · `__Registry` 14 · `__Writer` 14 · `__Parser` 10 · `__Runner` 9 · `__Manager` 7 · `__Factory` 4 · `__Watchdog` 2 · `__Poller` 1 ### The double-underscore rule **`__` is the word separator inside a compound name; `_` separates words within one term.** `Schema__Image__Build__Request` reads as *Schema · Image · Build · Request*. `Safe_Str__IP__Address` keeps `Safe_Str` as one term. **3,871 of 3,999 filenames contain `__`.** The documented normalisation (rule 20) handles the one hard case: the spec uses names like `SGraph-AI` with a hyphen, which is not a legal Python identifier. **Class and module names use `SGraph_AI`; repo roots and test filenames may keep `SGraph-AI`.** ### `__init__.py` stays empty Rule 22, and it holds at **299 of 302 (99%)**. Callers import from the fully-qualified per-class path; nothing is ever re-exported. The rule carries its own warning, learned the hard way: *"Never commit an empty `__init__.py` in a folder that shares a name with a sibling `.py` module: Python's import system prefers the package and every import under the module breaks."* --- ## 3. `Type_Safe` — runtime validation instead of static typing From `osbot-utils`. Rule 1: **all classes extend it — no plain Python classes.** Rule 82 of the tooling table is blunter: *"**Never use Pydantic. No Literals.**"* Of 1,034 classes in the new tree: | Base | Count | |---|---:| | `Type_Safe` | 506 | | `TestCase` | 169 | | `Safe_Str` | 78 | | `str, Enum` | 69 | | `Fast_API__Routes` *(a Type_Safe descendant)* | 46 | | `Type_Safe__List` | 44 | | `Schema__Step__Base` *(a Type_Safe descendant)* | 25 | | `Safe_Int` / `Safe_UInt` / `Enum` | 27 | **Excluding tests and enums, essentially every class is in the `Type_Safe` lineage.** Do not publish "48% extend Type_Safe" — it is true and it is misleading. What it buys: attributes are validated at construction, so **a value that exists is a value that is valid**. There is no separate validation layer, no schema-parse step at the boundary, and no `if not isinstance(...)` scattered through the code. It is also why the absence of a type-checker matters less here than it would elsewhere — though see `08__` §1. --- ## 4. Constrained primitives — the type *is* the validation Rule 2: *"zero raw primitives — no `str`, `int`, `float`, `list`, `dict` as attributes."* `sg_compute/primitives/` alone holds 27, and the pattern is uniform: ```python # ═══════════════════════════════════════════════════════════════════════════════ # SG/Compute — Safe_Str__IP__Address # IPv4 address string, e.g. "1.2.3.4". Empty = not yet assigned. # ═══════════════════════════════════════════════════════════════════════════════ import re from osbot_utils.type_safe.primitives.core.Safe_Str import Safe_Str from osbot_utils.type_safe.primitives.core.enums.Enum__Safe_Str__Regex_Mode import Enum__Safe_Str__Regex_Mode class Safe_Str__IP__Address(Safe_Str): max_length = 45 # covers IPv4 + IPv6 regex = re.compile(r'^[0-9a-fA-F.:]*$') regex_mode = Enum__Safe_Str__Regex_Mode.MATCH strict_validation = True allow_empty = True ``` Five class attributes, all aligned, and a **trailing comment carrying the reasoning** (`# covers IPv4 + IPv6`) — which is the estate's substitute for a docstring. The domain vocabulary is visible in the file list: `Safe_Str__AWS__Region`, `Safe_Str__Docker__Image`, `Safe_Str__Instance__Type`, `Safe_Str__Node__Name`, `Safe_Str__Pod__Name`, `Safe_Str__SSM__Path`, `Safe_Str__Spec__Id`, `Safe_Int__Port`, `Safe_Int__Max__Hours`, `Safe_Int__Exit__Code`. **Naming a type is how a domain concept gets recorded.** That is the argument for the page. --- ## 5. Layout and formatting **Banners.** `# ═` × 79, three content lines (product — class name — purpose), `# ═` × 79. Present on **3,120 of 3,999 files**, and **100% of the 992 class-defining files in the new tree.** Rule 7 adds a caveat learned from GitHub: *"**Python files only.** In Markdown, `#` is heading syntax — a `# ═══` header block renders as a stack of H1s."* **Alignment.** Measured: - **Schema attribute colons: 100% aligned** — 46 of 46 files with two or more annotated attributes - **Class attribute values: aligned** — see the `Safe_Str` example - **Import keywords: 39% aligned** — 321 of 817 files with two or more `from X import Y` lines have every import at a single column. **This is the estate's least consistent formatting rule and the easiest to automate.** **Comments.** Rule 8: *"inline comments only — no docstrings, ever."* Compliance is **99.7%** — 3 violations in 992 files. Trailing comments carry the reasoning; the banner carries the purpose. **Private methods.** Rule 9: *"no underscore prefix for private methods."* Compliance is **91%** — 97 files in the new tree use `def _method`. Either the rule is Python-only-and-widely-ignored, or it needs revisiting. The document does not say. `08__` Q2. --- ## 6. Testing Rule set, verbatim, from *Testing — Non-Negotiable*: > 1. **No mocks. No patches.** Use `register_playwright_service__in_memory()` and `in_memory_stack`-style composition. > 2. **Assert on contracts** — schemas, status codes, persisted artefacts — not implementation details. > 3. **Real Chromium for integration tests.** Gate on `SG_PLAYWRIGHT__CHROMIUM_EXECUTABLE`; skip cleanly when absent. > 4. **Deploy-via-pytest.** Deploy tests are numbered (`test_1__create_lambda`, `test_2__invoke__health_info`, …) and run top-down. **"No mocks, no patches" is the strongest opinion in the whole rule set** and it deserves its own page. The alternative is real in-memory composition, which is only affordable because `Type_Safe` objects are cheap to build — the type system and the testing philosophy are the same decision. 169 classes extend `TestCase`, so tests are class-based. And **4,785 tests run in 81 seconds**, which is the evidence that the no-mocks position is affordable rather than aspirational. --- ## 7. Responsibility boundaries — rules that name a single owner Rules 16–19 are unusual and worth publishing as a pattern: > 16. **`Step__Executor` is the ONLY class that calls `page.*` Playwright methods** (with a `Browser__Launcher` carve-out for process lifecycle) > 17. **`Artefact__Writer` is the ONLY class that writes to sinks** > 18. **`Request__Validator` contains ALL cross-schema validation** > 19. **Routes have no logic** — pure delegation to `Playwright__Service` Each names exactly one owner for a capability, and rule 16 is **enforced by a CI guard** that fails the build if any raw `browser.new_context(` appears outside `Page__Factory`. That is the model: **a boundary rule with a test behind it.** Three of the four have no such test. --- ## 8. What a linter config would encode Ordered by value, for `/enforce/`: 1. **Import alignment** — the 61% gap, and the only formatting rule that is measurably inconsistent 2. **No docstrings** — trivial (`ruff` D-rules inverted), currently 3 violations 3. **Banner present and well-formed** — a custom check, ~20 lines 4. **Filename equals class name, one class per file** — a custom check 5. **No raw primitives as class attributes** — the highest-value rule and the hardest to express; probably a custom AST check 6. **Ban `Pydantic`, `Literal`, direct `boto3`** — three import bans, one line each 7. **`__init__.py` empty** — trivial 8. **No `_` prefixed methods** — trivial, but **decide the rule first** (§5) Items 2, 6 and 7 are a single `ruff` config block. Items 1, 3, 4, 5 and 8 are a small `tests/ci/` module in the style of the four that already exist. --- ## 9. Dependencies — the `osbot-*` family `osbot-utils` (the source of `Type_Safe` and `Safe_Str`, 885 mentions across the corpus), `osbot-aws`, `osbot-fast-api`, `osbot-fast-api-serverless`, `memory_fs`, `mgraph-db`, `mgraph-ai-service-cache`. All Apache-2.0, all under the `owasp-sbot` GitHub organisation. Two hard rules govern their use: > **Type system** — `Type_Safe` from `osbot-utils`. **Never use Pydantic. No Literals.** > **AWS operations** — `osbot-aws`. **Never use boto3 directly** (narrow documented exception for the Lambda Function URL two-statement permission fix). **Note the exception is documented rather than silent.** That is a convention in itself and worth naming on the site: a banned thing with one written carve-out, rather than a banned thing with quiet violations. --- This document is released under the Creative Commons Attribution 4.0 International licence (CC BY 4.0). ============================================================================== source: /briefs/02__javascript.md ============================================================================== # 02 — JavaScript 50 files, no framework, no build step, and a component system nobody has written down. **This is the most original and least documented convention in the estate.** --- ## 1. The complete example `components/sg-compute/sg-compute-left-nav/v0/v0.1/v0.1.0/sg-compute-left-nav.js`, verbatim: ```js /** * sg-compute-left-nav — vertical icon-rail navigation for the admin dashboard. * * Items: Compute / Storage / Settings / Diagnostics. * Click fires sp-cli:nav.selected { view } on document. * * @module sg-compute-left-nav * @version 0.1.0 */ import { SgComponent } from 'https://dev.tools.sgraph.ai/components/base/v1/v1.0/v1.0.0/sg-component.js' class SgComputeLeftNav extends SgComponent { static jsUrl = import.meta.url get resourceName() { return 'sg-compute-left-nav' } get sharedCssPaths() { return ['https://dev.tools.sgraph.ai/components/tokens/v1/v1.0/v1.0.0/sg-tokens.css'] } onReady() { this._current = 'compute' this.shadowRoot.querySelectorAll('.nav-item').forEach(btn => { btn.addEventListener('click', () => this._select(btn.dataset.view)) }) this._update() } _select(view) { if (view === this._current) return this._current = view this._update() document.dispatchEvent(new CustomEvent('sp-cli:nav.selected', { detail: { view }, bubbles: true, composed: true, })) } _update() { this.shadowRoot.querySelectorAll('.nav-item').forEach(btn => { btn.classList.toggle('selected', btn.dataset.view === this._current) btn.setAttribute('aria-current', btn.dataset.view === this._current ? 'page' : 'false') }) } } customElements.define('sg-compute-left-nav', SgComputeLeftNav) ``` --- ## 2. The component system **Native web components. 41 `customElements.define` across 50 files. No React, no Vue, no bundler, no build step.** The browser is the runtime. ### The three-file triplet Every component is exactly three files, same basename: ``` sg-compute-left-nav.js behaviour sg-compute-left-nav.html markup sg-compute-left-nav.css styles ``` `static jsUrl = import.meta.url` is what makes this work: the component knows its own URL, so `SgComponent` can fetch the sibling `.html` and `.css` without anything being told where they live. **Self-locating components are the mechanism that removes the build step.** ### The versioned CDN path ``` https://dev.tools.sgraph.ai/components//v1/v1.0/v1.0.0/.js ^^^ ^^^^ ^^^^^^ major minor patch — as directories ``` Three nested directories, one per semver level. A consumer pins at whatever depth it wants stability: `/v1/` follows the major, `/v1.0/` follows the minor, `/v1.0.0/` is frozen. **Immutable URLs, no lockfile, no `node_modules`, cacheable forever.** The same scheme is used locally under `components/`. What comes from the CDN today: `SgComponent` (the base class), `sg-tokens.css` (design tokens), `sg-vault-client.js`, `sg-vault-write.js`. ### The base class contract `SgComponent` supplies the lifecycle; components override three things: | Member | Purpose | |---|---| | `static jsUrl = import.meta.url` | self-location — **required** | | `get resourceName()` | the basename of the sibling `.html` / `.css` | | `get sharedCssPaths()` | tokens and shared sheets to adopt | | `onReady()` | the lifecycle hook — **not `connectedCallback` directly** | `onReady()` rather than `connectedCallback` is the tell: the base class handles the async fetch of the sibling files and calls `onReady()` once the shadow root is populated, so a component never has to think about whether its markup has arrived. ### Shadow DOM 6 files call `attachShadow` directly; the rest inherit it from `SgComponent`, and every component addresses its own markup through `this.shadowRoot`. Styles are scoped by `:host` (see `03__`). --- ## 3. Formatting, measured | Convention | Evidence | |---|---| | **4-space indent** | 3,791 indented lines are a multiple of 4; 148 are not | | **Single quotes** | **4,006 single vs 400 double** — 91% | | **No semicolons** | 531 statement lines without vs 401 with — the newer `components/` tree is consistently semicolon-free; the older `shared/` tree is not. See §6 | | **Trailing commas** | in multi-line object and array literals, consistently | | **Aligned object keys** | `detail: { view },` — the same alignment discipline as Python and CSS | | **`_` prefix for private** | universal in JS, **against Python rule 9**. See `06__` §3 | | **ESM everywhere** | 48 `type="module"` script tags; no UMD, no globals | | **Banner comments** | 15 of 50 files open with `// ── name — description ──` | **Two banner styles exist**: JSDoc blocks (`/** … @module … @version */`) on components, and `// ── … ──` box-drawing rules on shared modules. Python uses `# ═══`. **The estate has three banner characters for one idea** — `05__` §2. --- ## 4. Events, state and data **Events are namespaced and go through `document`:** ```js document.dispatchEvent(new CustomEvent('sp-cli:nav.selected', { detail: { view }, bubbles: true, composed: true, })) ``` `bubbles: true, composed: true` is what lets an event escape the shadow root. **The namespace is `sp-cli:` — the old CLI name — and it appears in 23 files.** That is a rename surface nobody has counted; see `06__` §3. **State is instance fields**, `_`-prefixed, set in `onReady()`. No store, no observable, no framework state layer. Cross-component state goes through the event bus and through purpose-built shared modules — `settings-bus.js`, `vault-bus.js`, `poll.js`. **Constants are frozen and centralised.** `shared/launch-defaults.js`, verbatim: ```js // ── launch-defaults.js — canonical launch constants ────────────────────────── // // Single source of truth. Both sg-compute-compute-view and sg-compute-launch-form // import from here. Update here only — do not duplicate locally. export const REGIONS = Object.freeze([ 'eu-west-2', 'us-east-1', 'ap-southeast-1', 'eu-west-1', 'us-west-2', ]) ``` **`Object.freeze` on every exported constant**, and a comment that names the consumers and forbids local duplication. That is the same *single source of truth* instinct that drives `manifest.py` and the repo-root `version` file. --- ## 5. Why no build step is the interesting claim It is worth arguing on the site rather than just reporting. **What it costs:** no TypeScript, no JSX, no tree-shaking, no minification, no dependency resolution, one network request per component file. **What it buys:** the source that runs is the source you read — no source maps, no build cache, no `node_modules`, no bundler upgrade treadmill, and **an immutable URL per version instead of a lockfile**. A component is deployable by copying three files to a path. And — the point that connects to `05__` §3 — **an agent reading the running page reads the actual code**, with no transpilation between what it sees and what executes. **Where it stops working:** at the point you need a dependency graph deeper than one level, or a package that only ships as CJS. Neither has happened yet in 50 files. --- ## 6. Inconsistencies to fix before publishing 1. **Semicolons.** `components/` is semicolon-free; `shared/` is not. **Pick one** — the newer tree suggests dropping them — and write the config. 2. **Two banner styles.** JSDoc on components, `// ──` on shared modules. Pick one per file type and say which. 3. **The `sp-cli:` event namespace** is legacy naming in 23 files. Rename with the rest (`sg-compute` pack `02__`), and note that renaming an event namespace is a breaking change for any listener outside the repo. 4. **`_private` in JS vs rule 9 in Python.** The rule set says no underscore prefix; the JavaScript uses it universally. **State that rule 9 is Python-only**, or change one of the two. --- ## 7. What a linter config would encode `eslint` with: 4-space indent · single quotes · no semicolons · trailing commas in multiline · `object-curly-spacing` · a custom rule requiring `static jsUrl = import.meta.url` in any class extending `SgComponent` · a ban on bare `connectedCallback` overrides in favour of `onReady()` · and a check that every component directory contains all three of `.js` / `.html` / `.css`. The last two are the ones that would actually catch bugs. --- This document is released under the Creative Commons Attribution 4.0 International licence (CC BY 4.0). ============================================================================== source: /briefs/03__html-and-css.md ============================================================================== # 03 — HTML and CSS 37 HTML files, 38 CSS files. Both follow from the component system in `02__`, and **CSS carries the estate's alignment discipline further than any other language.** --- ## 1. HTML — the component's markup half `sg-compute-left-nav.html`, verbatim: ```html