Skip to content

Commit 660ed00

Browse files
committed
docs(agents): state the app-vs-platform boundary once, so it stops being re-derived
Three seats decided this ad hoc on one day and each derivation differed, because nothing in AGENTS.md, CLAUDE.md or skills/ stated the rule. One new section, no other edit: - the deciding question — could this be written by something that has only the metadata, and no knowledge of this company? - the second question for publication — would a second app copy the implementation? (one consumer is a use, two is a contract) - the two anti-patterns — an app hand-copying a platform rule, and a platform capability that under-delivers silently Every lesson is carried self-contained (failure mode, discipline, boundary) with no issue-ID citation, per the 2026-08-12 ruling that check:pm-skill-id-lint enforces. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m
1 parent 52d5a52 commit 660ed00

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,38 @@ Boot the real composition with its real services, or do not claim an answer.
962962

963963
---
964964

965+
## App or platform — which work belongs where
966+
967+
**The deciding question: could this be written by something that has only the metadata,
968+
and no knowledge of this company?**
969+
970+
| Answer | Belongs in |
971+
|:--|:--|
972+
| **No** — it encodes the company's own judgement | the **metadata app**: a discount ceiling, who a case is assigned to, how won/lost is booked; its own objects, views and flows |
973+
| **Yes** — it only asks whether the metadata is self-consistent | the **platform**: reference integrity, translation coverage, view rosters, sharing-rule coverage, CRUD round-trips, RLS probes per declared position |
974+
| the subject is platform behaviour, the cost lands on the app | the **platform**, and it is a **gap** until it does — asserting what a hook does inside the platform's own sandbox is one |
975+
976+
**Second question, for a capability an app wants published: would a second app copy the
977+
implementation?** Yes ⇒ platform. A resolution wanted by four call sites inside one package
978+
stays package-private on exactly that test — **one consumer is a use, two is a contract**,
979+
and a symbol never published still moves without a major.
980+
981+
**An app never hand-copies a platform rule.** The copy diverges from the rule the build
982+
actually applies, so the app stays green while the platform refuses. A card wanting the
983+
platform's hook-body lowering pass turned out to want half a command that already ships
984+
(`os build --strict-body` fails a bundled-instead-of-lowered body with exit 1) and half an
985+
`os lint` rule that exists nowhere in the tree. One level up, the same shape ships a rule
986+
claiming "0 findings over the corpus" against a corpus that is not the app it names.
987+
988+
**A capability that under-delivers silently is worse than none.** `os verify` derived
989+
**zero** cases on a multi-package app and reported success; `verify.ts` names the shape —
990+
*a verifier that under-verifies reports success it never established*. An app that meets one
991+
writes its own and never comes back, so the order is fixed: **make the derived half
992+
trustworthy first, then take the hand-written half back.** That fix landed as an ordered
993+
pair — ledger the losses, then close them; reversing it just deletes protection.
994+
995+
---
996+
965997
## Degradation log levels — `warn` vs `error`
966998

967999
Nearly every `catch` in this repo is a best-effort degradation, and nearly every one of

0 commit comments

Comments
 (0)