실행 가능한 온톨로지 vs 지식 온톨로지: 「상속 없음, 공리 없음, 추론기 없음」이 왜 핵심인가
지식 온톨로지는 추론되기 위해, 실행 가능한 비즈니스 온톨로지는 검증되고 실행되기 위해 만들어진다. 증거는 키 하나다. abstract는 상속을 약속했고, 아무것도 하지 않았으며, 남겨지는 대신 제거되었다.
지식 온톨로지는 추론되기 위해 만들어진다. 실행 가능한 비즈니스 온톨로지는 검증되고, 검토되고, 실행되기 위해 만들어진다. ObjectStack README는 그 차이를 세 가지 거부 — 「no inheritance, no axioms, no reasoner」(상속 없음, 공리 없음, 추론기 없음) — 로 적고 있으며, 이 거부들은 로드맵의 빈칸이 아니다. 그것이 바로 모든 정의를 검사 가능하게, 모든 diff를 검토 가능하게 만드는 것이다: 당신이 쓸 수 있는 키는 런타임에 읽는 쪽이 있거나, 아니면 제거된다. 이 글은 그 주장을 끝까지 전개하며, 증거는 키 하나다.
그 키가 여기 있다. 지식 온톨로지의 클래스가 그럴 수 있듯이, abstract로 표시된 객체:
export const Party = ObjectSchema.create({
name: 'crm_party',
label: 'Party',
abstract: true,
sharingModel: 'private',
fields: { name: Field.text({ label: 'Name', required: true }) },
});
2026-07-17에 공개된 @objectstack/[email protected]에서 이 정의는 파싱되고 abstract는 true로 돌아온다. 현재 릴리스인 @objectstack/[email protected]에서는 거부된다:
Unrecognized key(s) on this object: `abstract`.
• `abstract` was removed from the spec (ADR-0049) — object inheritance/abstraction is not implemented, so an abstract object still got a table and was instantiable. Remove the key.
그 사이에 만들어진 것은 아무것도 없다. 상속은 오지 않았다. 바뀐 것은, 런타임이 한 번도 읽지 않은 키가 이유를 말하는 메시지와 함께 스펙에서 빠졌다는 것뿐이다. 아래 전부는 왜 그것이 한 종류의 온톨로지에는 옳은 수이고 다른 종류에는 틀린 수인지에 대한 논증이며, README, Business Ontology 개념 페이지, 이 제거를 관장하는 결정 기록, 그리고 공개된 패키지에서 — 묘사가 아니라 측정으로 — 끌어낸 것이다.
두 온톨로지, 두 가지 일
온톨로지라는 말은 같은 대화 안에서 서로 다른 두 가지를 가리키고, 정의 글은 이것을 실행 가능한 비즈니스 온톨로지가 「아닌」 세 가지 중 첫째로 꼽았다. 이 주제에 관한 README의 문단은 통째로 인용할 만큼 짧다:
Your app’s definition — objects and fields, relations, actions, permissions, flows, and agent and tool definitions — is a business ontology: open, versioned, and yours, not code scattered across a framework. It is executable, not a knowledge-representation ontology: no inheritance, no axioms, no reasoner — validated rather than reasoned over — and it is not a semantic layer over your existing systems (federating an external datasource is read-only by default and early).
— objectstack README.md, “What we mean by ontology”
(요지: 당신의 앱 정의 — 객체와 필드, 관계, 액션, 권한, 플로우, 에이전트와 도구 정의 — 는 비즈니스 온톨로지다: 열려 있고, 버전이 있고, 당신의 것이며, 프레임워크 곳곳에 흩어진 코드가 아니다. 그것은 실행 가능하며, 지식 표현 온톨로지가 아니다: 상속 없음, 공리 없음, 추론기 없음 — 추론되는 대신 검증된다 — 그리고 기존 시스템 위의 시맨틱 레이어도 아니다(외부 데이터소스 연합은 기본적으로 읽기 전용이고 초기 단계다).)
두 종류를 차례로 보되, 첫째를 진지하게 다루자. 더 오래되었고 더 엄밀한 쪽이기 때문이다.
지식 온톨로지는 추론을 위해 만들어진다. W3C의 OWL 2와 그 아래 RDF 스택에서는 클래스, 속성, 그리고 공리를 쓴다: 이 클래스는 저 클래스의 하위 클래스다; 이 두 클래스는 서로소다; 이 속성은 값을 최대 하나 가진다; 이 속성 체인은 저 다른 속성을 함의한다. 그런 다음 추론기가 모델 전체를 읽고 무엇이 따라 나오는지 도출한다. 클래스 계층은 선언되는 데 그치지 않고 계산된다. 개체는 누군가 타이핑한 클래스가 아니라 그것에 대해 알려진 것으로 분류된다. 공리 사이의 모순은 발견된다. 그리고 전체는 열린 세계 가정 아래 돌아간다: 없는 사실은 거짓이 아니라 미지다. 데이터가 여러 출처에서 오고, 어휘를 기관 사이에서 공유해야 하며, 질문이 「우리가 아는 모든 것에서 무엇이 따라 나오는가?」일 때 그것은 정확히 옳은 설계다. 시맨틱 레이어·지식 그래프와의 비교는 그 전통에 합당한 대접을 한다; 이 글에는 그 윤곽만 필요하다.
실행 가능한 비즈니스 온톨로지는 소프트웨어가 생성되고, 검증되고, 검토되고, 실행될 수 있도록 만들어진다. 개념 페이지는 파이프라인을 한 줄로 보여준다:
objectstack.config.ts -> objectstack.json -> ObjectStack runtime -> database · REST / realtime API · UI · MCP server
그리고 그것을 관장하는 규칙을 또 한 줄로: 「Nothing is reasoned over at runtime: what runs is what was validated.」(런타임에서는 아무것도 추론되지 않는다: 돌아가는 것은 검증된 것이다.) 정의는 한 사업체의 애플리케이션이며, 타입이 있는 메타데이터로 작성되고, Zod 스키마와 os validate로 검사된 뒤 실행된다. 도출된 사실로 이루어진 두 번째 산출물은 없다. 세계는 구성상 닫혀 있다: 정의가 말하는 것이 시스템이 하는 것이고, 정의가 말하지 않는 것은 시스템이 하지 않는다.
| 지식 온톨로지 | 실행 가능한 비즈니스 온톨로지 | |
|---|---|---|
| 무엇을 위해 만드는가 | 기술된 도메인에 대한 추론 | 애플리케이션 하나를 생성하고, 검증하고, 검토하고, 실행하는 것 |
| 정의의 단위 | 클래스, 속성, 개체, 공리 | 객체와 필드, 관계, 액션, 권한, 플로우, 에이전트와 도구 정의 |
| 정의를 읽는 것 | 추론기 — 모델 전체에서 함의를 도출한다 | 키마다 이름이 있는 런타임 읽기 주체 — 데이터베이스 드라이버, API, 권한 평가기, 콘솔, MCP 서버 |
| 런타임에 존재하지만 아무도 쓰지 않은 것 | 추론된 사실: 계산된 계층, 분류, 귀결 | 없음. 「돌아가는 것은 검증된 것이다.」 |
| 잘못된 정의는 어떻게 실패하는가 | 추론기가 보고하는 비일관성, 또는 아무도 예상하지 못한 함의 | 무엇이든 실행되기 전, 작성 시점의 위치가 있는 오류 |
| 시스템이 무엇을 하는지 알려면 어디를 보는가 | 모델 그리고 그것이 함의하는 것 | diff |
두 열은 순위가 아니다. 두 질문에 대한 두 답이며, 둘째 질문 — 검토자가 이 변경이 무엇을 하는지 알 수 있는가, 런타임이 동작하지 않을 정의를 거부할 수 있는가 — 이 애플리케이션이 답해야 하는 질문이다.
세 가지 거부, 하나씩
각 거부는 지식 온톨로지가 갖는 것이 옳은 무언가를 제거한다. 각각이 거기 있는 이유는 그것이 검토자와 게이트에 어떤 비용을 물리는가에 있다.
상속 없음
클래스 계층에서 자식은 부모의 제약을 상속하고, 어떤 클래스가 결국 어떤 제약 집합을 지게 되는지 알려주는 것은 추론기다. 어휘에는 그것이 기능이다: 일반적인 경우를 한 번 선언하고 엔진이 전파하게 두면 된다. 애플리케이션 정의에는 읽는 사람이 치르는 비용이다. 부모의 한 줄 변경이 모든 자식의 동작을 바꾸는데 그중 어느 것도 diff에 나타나지 않고, 「이 객체는 실제로 무엇을 강제하는가?」라는 질문에 그 객체 자신의 파일만으로는 답할 수 없다.
ObjectStack의 객체는 상속하지 않는다. 개념 페이지는 객체 사이의 유일한 연결 종류를 「Lookups and master-detail links between objects」(객체 사이의 lookup과 master-detail 연결)로 적는다 — 레코드 사이의 관계이며, 그것을 가진 객체 위에 선언된다. 모든 객체의 테이블, 필드, 권한, 보안 태세는 그 객체 위에 적혀 있으므로, 파일이 답의 전부이고 diff가 변경의 전부다.
공리 없음
공리는 추론기가 도출하는 데 쓰는 제약이다: 「모든 주문은 정확히 한 명의 고객을 가진다」와 고객이 둘인 주문에서, 추론기는 두 고객이 같은 개체라거나 모델이 비일관적이라고 결론 내린다. 실행 가능한 온톨로지에도 제약은 있다 — 필수 필드, 선택지, lookup 대상, CEL 술어, 모든 객체가 선언해야 하는 보안 태세 — 하지만 그것은 도출이 아니라 거부에 쓰인다. README의 두 번째 게이트는 이 문장이다: os validate는 「rejects metadata that type-checks but would fail silently at runtime: dangling bindings, bad CEL predicates, missing security posture」(타입 검사는 통과하지만 런타임에서 조용히 실패할 메타데이터를 거부한다: 매달린 바인딩, 잘못된 CEL 술어, 빠진 보안 태세). 제약을 어기는 정의는 귀결을 얻지 않는다. 위치가 있는 오류를 얻는다.
추론기 없음
이것이 다른 두 거부가 섬기는 거부다. 추론 엔진은 두 번째 진실의 원천이다: 그것이 런타임에 도출하는 사실은 검토자가 읽을 수 있는 어디에도 적힌 적이 없다. 「Nothing is reasoned over at runtime: what runs is what was validated」가 개념 페이지의 규칙이고, 그 실천적 형태는 정의 글이 준 것이다: 권한이 diff에 없으면 시스템에도 없다. 런타임은 산출물에서 표면들 — 스키마, API, UI, MCP 도구 — 을 도출하고, 모든 호출에서 정의를 강제한다. 정의가 말하지 않은 것을 결론 내리지 않는다.
증거: 상속을 약속하고 아무것도 하지 않은 키
추론기를 거부하는 것은 말하기는 싸고 지키기는 비싸다. 기능처럼 들리는 키를 두고 가장 쉬운 일은 스키마에 남겨 두고 나중에 무언가가 의미를 부여하게 두는 것이기 때문이다. abstract는 그것이 어떤 모습인지, 그리고 그 반대가 어떤 모습인지 보여준다.
이전: 선언되고, 파싱되고, 읽히지 않음
@objectstack/[email protected]에서 객체 스키마는 이 키를 선언했고, 설명은 추상 클래스의 교과서적 정의였다:
abstract: z.boolean().optional().default(false).describe("Is abstract base object (cannot be instantiated)")
Studio의 객체 폼은 그것을 불리언 필드로 나열했고 도움말은 「Abstract base (cannot be instantiated)」였다. 그리고 같은 패키지 자체의 활성 장부(liveness ledger) — 런타임 읽기 주체가 존재하는지를 키마다 적기 위해 프로젝트가 관리하는 파일 — 는 이렇게 말했다:
"abstract": {
"status": "dead",
"evidence": "no runtime reader",
"authorWarn": true,
"authorHint": "No runtime reader — an abstract object still gets a table and is instantiable. Object inheritance/abstraction is not implemented."
}
그러니까 15.1.1에서 키는 파싱되고, 폼은 그것을 제공하고, 파싱 결과는 abstract: true를 담고 있었으며 — 장부의 말대로 — 추상 객체는 「still gets a table and is instantiable」(여전히 테이블을 얻고 인스턴스화할 수 있다), 그 줄이 없는 것과 똑같이. 지식 온톨로지에서 추상 클래스는 추론기가 지키는 진술이다. 여기서는 아무것도 지키지 않는 진술이었다: 유효한 문법, diff 안의 그럴듯한 한 줄, 그리고 읽는 쪽 없음.
규칙: 강제됨, 실험적, 또는 부재
이를 관장하는 결정 기록은 ADR-0049다. 보안 속성에 대해, “found that roughly half of all spec properties are dead”(스펙 속성의 대략 절반이 죽어 있음을 발견한) 감사 뒤에 쓰였고, 규칙을 세 상태로 적는다:
- Enforced — a runtime consumer reads it and changes a decision (
file:line).
experimental — explicitly marked and documented as not yet enforced, so authoring it is a known no-op (roadmapped, not a promise).
- Absent — removed from the spec.
Shipping a security property in a fourth state — parsed, unmarked, unenforced — is prohibited. This is the enforce-or-remove gate.
(요지: 강제됨 — 런타임 소비자가 그것을 읽고 결정을 바꾼다(file:line). experimental — 아직 강제되지 않음으로 명시적으로 표시되고 문서화되어, 그것을 쓰는 것은 알려진 무동작이다(로드맵에는 있지만 약속은 아니다). 부재 — 스펙에서 제거됨. 네 번째 상태 — 파싱되고, 표시 없고, 강제되지 않음 — 로 보안 속성을 출시하는 것은 금지된다. 이것이 강제-아니면-제거 게이트다.)
그 이유는 보안 키만이 아니라 어떤 키에든 중요한 것이다: “A security property that parses but does nothing is worse than absent: it produces a false sense of compliance.”(파싱은 되지만 아무것도 하지 않는 보안 속성은 없는 것보다 나쁘다: 거짓된 준수감을 만든다.) 그리고 약속된 기능이 없을 때의 기본값은 제거다: “Removal is preferred over marking when there is no committed roadmap for the property — a smaller spec surface is the stronger default pre-MVP.”(그 속성에 확약된 로드맵이 없을 때는 표시보다 제거가 낫다 — 더 작은 스펙 표면이 MVP 이전의 더 강한 기본값이다.) abstract는 보안 키가 아니다; ADR 자체의 범위 메모는 저장소가 “cites this ADR as the enforce-or-remove policy for spec-property retirement generally”(이 ADR을 스펙 속성 퇴역 전반의 강제-아니면-제거 정책으로 인용한다)고 기록하고, 그것을 퇴역시킨 작업 지시 #2377는 그 일반화가 왜 의도적인지 말한다: “Authoring them is a false affordance — especially dangerous for AI-authored metadata.”(그것들을 작성하는 것은 거짓 어포던스다 — AI가 작성하는 메타데이터에는 특히 위험하다.)
이후: 무엇을 해야 할지 알려주는 묘비
제거는 16.0.0에 실렸다. 패키지 변경 이력은 한 문장으로 기록한다: “object tags/active/abstract: ObjectSchema.create() now throws a located error naming the removal. None gated anything at runtime — remove them.”(ObjectSchema.create()는 이제 제거를 지목하는 위치 있는 오류를 던진다. 어느 것도 런타임에서 아무것도 막지 않았다 — 제거하라.) 오늘 이 키는 객체 스키마의 미지 키 안내에 있는 묘비이고, 그것을 쓰는 모든 작성자가 보게 될 메시지는 이 글 맨 위의 그것, object.zod.ts에 있는 것이다:
abstract:
'`abstract` was removed from the spec (ADR-0049) — object ' +
'inheritance/abstraction is not implemented, so an abstract object still ' +
'got a table and was instantiable. Remove the key.',
활성 장부의 object 행은 기록을 보존한다: 「tags/active/abstract REMOVED (#2377) — tombstoned in UNKNOWN_KEY_GUIDANCE」. 이전과 이후는 공개된 패키지 위에서, 위의 Party 객체를 각 버전으로 파싱해 측정했다:
@objectstack/spec | ObjectSchema.create() | ObjectSchema.safeParse() |
|---|---|---|
| 15.1.1(2026-07-17) | 수락; abstract: true 유지 | 수락; abstract: true 유지 |
| 16.0.0(2026-07-21) | 오류를 던지며 제거를 지목 | 수락; abstract를 조용히 제거 |
| 17.7.0(2026-10-06) | 오류를 던지며 제거를 지목 | 거부: unrecognized_keys, 처방 포함 |
가운데 행은 한 문장을 들일 만하다. 16.0.0에서 작성 경로는 닫혔고 파싱 경로는 닫히지 않았다 — parse()는 여전히 말 한마디 없이 키를 버렸다. 스키마 자체의 주석이 Zod의 기본 .strip()과 #1535로 거슬러 올라가는 동작인데, 거기서는 객체 수준의 workflows: [...]가 「vanished with no error, no warning, and a green tsc」(오류도, 경고도 없이, tsc는 녹색인 채로 사라졌다). 17.x 메시지는 마지막 문장에서 스스로 그렇게 말한다: “Until this shape was closed these were dropped silently on the PARSE path — ObjectSchema.create() has rejected them, but defineStack({ objects }), /api/v1/meta/types/object and the Studio form all go through parse(), which did not.”(이 형태가 닫히기 전까지 이것들은 PARSE 경로에서 조용히 버려졌다 — ObjectSchema.create()는 거부해 왔지만, defineStack({ objects }), /api/v1/meta/types/object, Studio 폼은 모두 parse()를 거치며, 그것은 거부하지 않았다.) 키 하나를 닫는 것은 결정 하나가 아니다; 진입점마다 결정 하나이며, 한 진입점에서는 완전하고 다른 진입점에서는 침묵하는 게이트는 다른 외투를 걸친 네 번째 상태다.
왜 이것이 핵심인가
장부가 「no runtime reader」라고 적은 그 순간, 정직한 수는 둘이었다. 객체 상속을 만들어 abstract: true에 읽는 쪽과 의미를 주거나. 키를 제거하거나. 지식 온톨로지의 습관 — 그것이 비롯된 전통에서는 실수가 아니라 습관이다 — 은 선언을 남겨 두는 것이다. 그 전통에서 의미는 모델에 살고 엔진이 그것을 지키기 때문이다. 실행 가능한 쪽의 습관은 정반대다: 당신이 쓸 수 있는 키의 집합이 런타임이 하는 일의 집합이고, 읽는 쪽이 없는 키는 대기 중인 기능이 아니라 대기 중인 검토자의 거짓 믿음이다.
그것을 모든 키에 읽는 쪽을이라 부르자. 「추론되는 대신 검증된다」의 구체적 형태다. 검증기는 모든 용어에 소비자가 있는 어휘 위에서만 완전할 수 있다; 어떤 용어가 파싱되지만 읽히지 않는 순간, 「유효하다」는 「말한 대로 할 것이다」를 뜻하지 않게 된다. abstract 제거는 온톨로지를 작게 만들기 위한 것이 아니었다. 게이트를 통과한 정의는 런타임이 강제할 정의라는 약속을 지킨 것이다.
검토자가 얻는 것, 에이전트가 얻는 것
변경을 검토하는 사람에게 보상은 diff가 곧 동작이라는 것이다. 열어 볼 부모도, 계산할 함의도, 있을 수도 없을 수도 있는 기능에 효과가 달린 키도 없다. sharingModel: 'private'이 diff에 있으면 레코드는 비공개이고, 권한이 diff에 없으면 아무도 갖지 않는다. 「이 줄은 무엇을 하는가?」는 그 줄이 가진 런타임 읽기 주체가 답하고, 읽는 쪽이 없는 줄은 애초에 diff에 들어갈 수 없다.
변경을 쓰는 에이전트에게 보상은 같은 사실을 반대편에서 본 것이다. AI가 작성한 메타데이터가 왜 통하는가에 대한 README의 주장은 “an agent’s errors become located, corrective text it can read and fix itself”(에이전트의 오류는 위치가 있는 교정 텍스트가 되어, 에이전트가 스스로 읽고 고칠 수 있다)이다. 거짓 어포던스는 바로 그것을 무너뜨린다: 예제에서 형식을 배우는 에이전트는 강제되는 키와 파싱만 되는 키를 구별할 수 없다. 둘 다 검증을 통과하고, 둘 다 권위 있어 보이고, 둘 다 샘플에 나타나기 때문이다 — 「선언 vs 강제」 용어 항목이 유효하고, 그럴듯하고, 비활성인 선언이라 기술하는 실패다. 키를 제거하고 「Remove the key.」로 끝나는 묘비를 남기는 것은, 그 실패를 문제가 있었음을 사람이 알아차릴 필요도 없이 에이전트가 스스로 수행할 수 있는 한 줄 수정으로 바꾼다.
추론기를 위한 변호: 이것이 하지 않는 것
이 논증의 정직한 판본은 실행 가능한 온톨로지가 무엇을 포기하는지 말해야 한다. 포기하는 것이 진짜이기 때문이다.
추론하지 않는다. 함의도, 기술에 의한 분류도, 모델 전체에 걸친 일관성 검사도 없다. 도출된 사실이 당신에게 필요한 제품이라면 — 「이 만 건의 레코드 중, 우리가 아는 바로는, 어느 것이 고위험 거래상대방의 인스턴스인가?」 — 추론기는 답하고 검증기는 답하지 않는다.
열린 세계 추론을 하지 않는다. 닫힌 세계가 이 설계의 요점 전부이고, 본성상 부분적인 데이터에는 틀린 가정이다: 조직들 사이에서 공유되는 어휘, 당신의 시스템이 그것을 참으로 만드는 사실을 본 적이 없어도 참인 레코드. 지식 온톨로지는 그 경우를 위해 만들어졌고 이것은 아니다.
스키마 수준 상속을 하지 않는다. 기반 객체가 없다. 여섯 객체가 공유하는 필드는 여섯 객체에 선언되거나, 공유 객체를 가리키는 lookup으로 명시적으로 모델링된다. 이 반복은 의도적이다 — 그것이 각 객체의 파일을 답의 전부로 만든다 — 그러나 여전히 반복이고, 반복이 갖는 유지보수 비용을 진다.
두 가지가 같은 것이라고 결정하지 않는다. 한 시스템의 「customer」와 다른 시스템의 「account」가 하나의 엔티티인지는 누군가가 해야 하는 선언이지 런타임이 끌어내는 추론이 아니다; 엔터프라이즈 온톨로지 글은 그 정렬이 어떤 모델에서든 여전히 일인 이유를 다룬다.
그리고 한 가지 한계는 형식이 아니라 규율 자체에 속한다: 「검증됨」은 검증기가 참인 만큼만 참이다. ADR-0049 뒤의 감사는 규칙이 존재하기 전에 스펙 속성의 절반이 죽어 있음을 발견했다; 활성 장부와 그것을 읽는 게이트가 그 뒤로 규칙을 참으로 유지하는 것이고, 그것은 한 번 도달하는 상태가 아니라 상시적인 유지보수다. abstract 이야기는 이 규율이 실천되고 있다는 증거이지, 끝났다는 증거가 아니다.
호스팅으로, 또는 자체 인프라에서
README는 이 루프 — 에이전트가 당신의 저장소에 타입 있는 메타데이터를 쓰고, 게이트가 동작하지 않을 것을 거부하고, 런타임이 통과한 것을 실행한다 — 를 설명한 뒤 이렇게 말한다: 「이를 실행하기 위해 ObjectStack 저장소는 ObjectOS Community(ghcr.io/objectstack-ai/objectstack 이미지, os start, Console로 이루어진 무료 직접 호스팅 에디션)를 제공하며, ObjectOS Cloud는 호스팅 에디션, ObjectOS Enterprise는 직접 운영하는 라이선스 에디션입니다.」 온톨로지는 일반적인 ObjectStack 메타데이터입니다. ObjectOS Cloud 또는 ObjectOS Enterprise에서 내보내 오픈소스 ObjectStack 런타임에서 실행하는 기능은 계획 중입니다. 게이트는 어느 호스트에서나 같고, 그것이 지키는 온톨로지도 같다.
거부를 직접 시험해 보기
README의 에이전트 경로는 이 글이 다루는 산출물을 몇 분 안에 만들어 내고, 볼 가치가 있는 부분은 그 거부다.
npm create objectstack@latest my-app && cd my-app
코딩 에이전트에서 프로젝트를 열고 비즈니스 객체 하나 — 고객, 티켓, 작업 지시 — 를 설명하라. 그런 다음 이 글이 시작한 그 줄을 요구하라: 다른 객체들의 기반이 될 테니 abstract: true를 추가해 달라고. 어느 게이트가 먼저 닿든 — 편집기의 타입 게이트든, 빌드 시의 ObjectSchema.create()든 — 위에 인용한 메시지로 거부하고, 메시지는 수정법으로 끝난다. 에이전트가 그 수정을 받아들이게 하고, 결과를 미리 보라:
npx os dev --ui # → http://localhost:3000/_console/
diff에서 보게 될 것은 기반도, 상속받은 어떤 것도, 런타임이 읽지 않는 키도 없는 객체다 — 즉, 검토할 수 있을 만큼 작고 실행할 수 있을 만큼 엄격한 정의다. 에이전트에게 방향 잡기가 필요하다면 에이전트를 ObjectStack에 겨누는 법이 규칙 파일, 스킬 번들, 도구 서버를 다룬다. README의 세 가지 거부는 이 형식에 없는 것이 아니다. 그것이 강제하는 것이다.