You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
borromeanRings today gates how well code is written (build, lint, types, tests, security, layout) and what engineering surround exists ([hygiene].requires), and it adjusts checks per language (ADR-0015). What it does not yet gate is whether an application has the capabilities an app of its kind must have to be correct, safe, and complete.
An AI agent asked to "build a web API" will produce something that passes the quality gate (clean, typed, tested) yet is missing things that are non-negotiable for that app type — input validation at the boundary, authN/authZ, rate limiting, non-leaking error handling, a health endpoint, secrets from the environment. The agent doesn't know what "complete" means for this archetype, and nothing fails closed when those are absent. That's a correctness and security gap — exactly the kind of thing a meta-harness should make deterministic instead of leaving to agent taste.
Proposed change
Add an application-archetype dimension to the spine. A project declares its kind:
[project]
language = "python"kind = "web-api"# selects a capability profile (new)
Each capability profile (web-api, web-app, cli, library, worker, data-pipeline, embedded/firmware, …) declares a set of required capabilities, each with two halves:
A fail-closed check (checks/profiles/<kind>/*) asserting the capability is present and wired — producing a receipt like every other check.
An agent-facing playbook — the best-practice options/libraries for that capability and how to implement it well with an AI agent (loaded only when relevant, the way cs130-se routes by task).
Worked example — web-api profile (illustrative)
Required capability
Deterministic check (fail-closed)
Playbook covers
Input validation at boundaries
a declared validation layer is present + exercised by a test
schema validation libs, where to validate, fail-fast
AuthN/AuthZ
declared auth mechanism present + a test asserting unauthorized access is rejected
session vs token vs OAuth, least-privilege
Rate limiting
declared limiter wired on public endpoints
algorithms, per-key limits, 429 semantics
Non-leaking error handling
error handler present + test asserting no stack/secret in responses
structured errors, safe messages
Health/readiness endpoint
endpoint exists + responds
liveness vs readiness
Secrets management
no hardcoded secrets (extends 50_security) + env/secret-manager usage declared
env vars, secret managers, rotation
Worked example — embedded profile (illustrative; shows the range)
Required capability
Deterministic check (fail-closed)
Playbook covers
Deterministic memory
no dynamic allocation after init; no malloc/heap in ISRs; bounded stack usage
brown-out detection; safe default outputs on reset/fault
safe-state design, hardware fault handling
Coding-standard compliance
MISRA C / static analysis (cppcheck, clang-tidy) passes; no UB; no exceptions/RTTI where banned
MISRA rationale, UB avoidance, freestanding C/C++
Off-target testability
hardware-abstraction layer present so logic is testable without hardware
HAL seams, host/simulation tests, HIL
The determinism question (the crux)
"Does this API have good rate limiting?" can't be fully verified statically — so profiles use declare-and-verify, the same model as [hygiene].requires and the coverage ratchet: the project declares which mechanism satisfies each required capability; the check verifies the declared mechanism is present and backed by a test/config artifact, failing closed if a required capability is undeclared or unevidenced. borromeanRings makes the requirement deterministic even where fully-automatic quality detection isn't possible; the playbook raises implementation quality.
Enforcement richness is archetype-dependent. Some profiles are far more statically checkable than others: embedded practices like "no heap in ISRs", volatile on shared state, and MISRA compliance are real static-analysis gates, whereas "good rate limiting" leans on declare-and-verify. The profile model accommodates both — a check is as strict as its archetype permits, falling back to declare-and-verify only where automatic detection is undecidable.
Capability profiles must be evolvable; a frozen checklist becomes wrong as the frontier moves:
Profiles are declarative, versioned data — not hardcoded check logic. Adding, retiring, or changing a required capability is a data/config edit, not a rewrite. Each profile carries a version.
Decouple the durable "what" from the volatile "how." The capability ("validate input at boundaries", "no heap in ISRs") changes slowly; the playbook ("use library X / algorithm Y") changes fast. Keep them in separate layers so best-practice churn lives in the playbook, not the gate.
Per-project override + pinning. A project can extend, relax (with recorded rationale), or pin a profile version for reproducibility — consistent with the opt-in config spine (ADR-0010). A changed best practice never silently breaks a passing build; upgrades are explicit and reviewable.
Lifecycle, not silent edits. Capabilities graduate advisory → required (or retire) as consensus shifts; every change is recorded (ADR trail / changelog).
This profile system is the consumer of the frontier-tracking process: that process discovers and validates how best practices change; this system is where validated changes land — as versioned profile/playbook updates rather than ad-hoc rewrites.
Scope / non-goals
Not a scaffolding/codegen tool: borromeanRings does not implement features or generate the app. The agent builds; borromeanRings declares the required set, gates completeness, and routes to best practices. (Manifesto: stay narrow.)
Profiles are opt-in and declared (empty/absent kind ⇒ feature off), consistent with ADR-0010.
One global checklist for all apps — rejected: capability needs are archetype-specific; a CLI doesn't need rate limiting, an MCU doesn't allocate on the heap.
Pure static detection as the sole mechanism — rejected: undecidable in general; declare-and-verify is honest and fail-closed.
Playbooks only (guidance, no gate) — rejected: borromeanRings turns standards into gates, not suggestions.
Fit with the roadmap
Post-v0 epic (spans many checks + playbooks + profile selection). Land after current increments are proven (Lean: don't build deferred components early). Phasing: (1) profile selection in the spine + one archetype (web-api) with 2–3 highest-value capabilities; (2) the playbook/skill-routing half; (3) more archetypes once proven.
Open questions
Archetype taxonomy + granularity — e.g., does embedded split into bare-metal / RTOS / embedded-Linux (very different memory and concurrency rules), and how do sub-types inherit a base profile?
Do playbooks live as skills (skills/) or routed reference docs (like cs130-se)?
How does a profile compose with language (kind × language matrix)?
Per-capability severity — all fail-closed, or some advisory at first?
Versioning & upgrade policy — pin (reproducible, opt-in upgrades) vs float (always-current, may newly fail). Likely pin-by-default with explicit upgrades.
Problem / motivation
borromeanRings today gates how well code is written (build, lint, types, tests, security, layout) and what engineering surround exists (
[hygiene].requires), and it adjusts checks per language (ADR-0015). What it does not yet gate is whether an application has the capabilities an app of its kind must have to be correct, safe, and complete.An AI agent asked to "build a web API" will produce something that passes the quality gate (clean, typed, tested) yet is missing things that are non-negotiable for that app type — input validation at the boundary, authN/authZ, rate limiting, non-leaking error handling, a health endpoint, secrets from the environment. The agent doesn't know what "complete" means for this archetype, and nothing fails closed when those are absent. That's a correctness and security gap — exactly the kind of thing a meta-harness should make deterministic instead of leaving to agent taste.
Proposed change
Add an application-archetype dimension to the spine. A project declares its kind:
Each capability profile (
web-api,web-app,cli,library,worker,data-pipeline,embedded/firmware, …) declares a set of required capabilities, each with two halves:checks/profiles/<kind>/*) asserting the capability is present and wired — producing a receipt like every other check.cs130-seroutes by task).Worked example —
web-apiprofile (illustrative)50_security) + env/secret-manager usage declaredWorked example —
embeddedprofile (illustrative; shows the range)malloc/heap in ISRs; bounded stack usagevolatile; ISRs short + non-blocking; critical sections guard shared stateThe determinism question (the crux)
"Does this API have good rate limiting?" can't be fully verified statically — so profiles use declare-and-verify, the same model as
[hygiene].requiresand the coverage ratchet: the project declares which mechanism satisfies each required capability; the check verifies the declared mechanism is present and backed by a test/config artifact, failing closed if a required capability is undeclared or unevidenced. borromeanRings makes the requirement deterministic even where fully-automatic quality detection isn't possible; the playbook raises implementation quality.Enforcement richness is archetype-dependent. Some profiles are far more statically checkable than others: embedded practices like "no heap in ISRs",
volatileon shared state, and MISRA compliance are real static-analysis gates, whereas "good rate limiting" leans on declare-and-verify. The profile model accommodates both — a check is as strict as its archetype permits, falling back to declare-and-verify only where automatic detection is undecidable.Flexibility / evolvability (first-class requirement)
Capability profiles must be evolvable; a frozen checklist becomes wrong as the frontier moves:
advisory → required(or retire) as consensus shifts; every change is recorded (ADR trail / changelog).This profile system is the consumer of the frontier-tracking process: that process discovers and validates how best practices change; this system is where validated changes land — as versioned profile/playbook updates rather than ad-hoc rewrites.
Scope / non-goals
kind⇒ feature off), consistent with ADR-0010.Alternatives considered
Fit with the roadmap
Post-v0 epic (spans many checks + playbooks + profile selection). Land after current increments are proven (Lean: don't build deferred components early). Phasing: (1) profile selection in the spine + one archetype (
web-api) with 2–3 highest-value capabilities; (2) the playbook/skill-routing half; (3) more archetypes once proven.Open questions
embeddedsplit into bare-metal / RTOS / embedded-Linux (very different memory and concurrency rules), and how do sub-types inherit a base profile?skills/) or routed reference docs (likecs130-se)?kind × languagematrix)?