Skip to content

Commit 273fa78

Browse files
authored
Merge pull request #99 from AdaWorldAPI/claude/medcare-bridge-lance-graph-wmx76z
docs(OGAR): SurrealQL-AST trap pre-flight spellbook + activation triggers
2 parents 7e67718 + 81f865e commit 273fa78

3 files changed

Lines changed: 243 additions & 2 deletions

File tree

CLAUDE.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,14 @@ alignment costs. Until measured: 3×4 stands.
184184
failure modes the apparatus caught.
185185
6. `docs/OGAR-AST-CONTRACT.md` — the IR type surface (THINK arm `Class`
186186
/ DO arm `ActionDef`+`ActionInvocation` / membrane `KausalSpec`).
187-
4. `docs/ARCHITECTURAL-DECISIONS-2026-06-04.md` — ADR-001..025
187+
7. `docs/SURREAL-AST-AS-ADAPTER.md` — the carved decision: SurrealQL
188+
AST is an adapter, not the spine; behavioral arm cannot live in DDL.
189+
Operational pre-flight: `docs/SURREAL-AST-TRAP-PREFLIGHT.md` (the
190+
spellbook — five questions, 90 seconds, MANDATORY before any
191+
producer→IR / transcode / codegen / `.surql` authoring session).
192+
8. `docs/ARCHITECTURAL-DECISIONS-2026-06-04.md` — ADR-001..025
188193
(ADR-026 pending).
189-
5. `.claude/agents/` — the 5+3 hardening pattern (5 research savants +
194+
9. `.claude/agents/` — the 5+3 hardening pattern (5 research savants +
190195
3 brutally-honest reviewers). Run it before any claim enters the
191196
canon. Theorem-checker rule 0: **pin the unit system first** (bits
192197
vs hex vs bytes — born from a real failure).
@@ -195,6 +200,13 @@ alignment costs. Until measured: 3×4 stands.
195200

196201
- **The Firewall (ADR-022/023):** no serialization in the hot path;
197202
the IR is wire-truth; inter-mailbox state is Batons.
203+
- **SurrealQL is an adapter, not a spine:** before any producer→IR /
204+
transcode / codegen / `.surql` authoring session, read
205+
`docs/SURREAL-AST-TRAP-PREFLIGHT.md` (five-question pre-flight, 90
206+
seconds). The behavioral arm cannot live in DDL — `DEFINE EVENT … WHEN
207+
… THEN …` carrying lifecycle is the "negative-beauty hijack"
208+
`SURREAL-AST-AS-ADAPTER.md` §0 rejects. Behavior flows producer →
209+
OGAR `Class`+`ActionDef` → adapter; never producer → DDL.
198210
- **PII:** never emit German PII labels (medcare-rs leaf-rename at the
199211
adapter is the guarantee). Word-boundary abort-guard before commit.
200212
- **No model identifier** in any committed artifact (chat only).

docs/SURREAL-AST-AS-ADAPTER.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# SurrealQL AST as the universal adapter — feasibility, beauty, and brutal honesty
22

3+
> **Operational extract** (pre-flight, 90 seconds, read BEFORE keyboard):
4+
> `docs/SURREAL-AST-TRAP-PREFLIGHT.md` — the spellbook. Five introspection
5+
> questions that fire BEFORE materialization, plus diagnostic signatures
6+
> for review. This doc is the *design* (the *why*); the preflight is the
7+
> *operational mirror* sessions run on themselves. Mandatory pre-read for
8+
> any producer→IR / transcode / codegen / `.surql` authoring session.
9+
310
> **Purpose.** Record the deliberate architectural decision on whether to use
411
> `surrealdb-ast` as the *universal* adapter / IR — for both DDL sources
512
> (SurrealQL itself) and non-DDL sources (Ruby AR, Python Odoo, Elixir Ecto,

docs/SURREAL-AST-TRAP-PREFLIGHT.md

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# SurrealQL AST trap — pre-flight introspection (the spellbook)
2+
3+
> **Operational extract** of `SURREAL-AST-AS-ADAPTER.md` (the design).
4+
> Read this BEFORE the keyboard fires — five questions, 90 seconds, one
5+
> mirror. If you finish all five, you've cleared the trap; if you stop
6+
> at any one, you've caught it pre-materialization.
7+
>
8+
> The pattern this protects against is **pre-cognitive**, not reasoned:
9+
> sessions don't argue their way in, they *reflex* their way in. This
10+
> doc exists because a mirror that fires before the reflex is cheaper
11+
> than a refactor that fires after.
12+
>
13+
> Status: **SPELLBOOK v0** (2026-06-22). Append-only.
14+
>
15+
> Grounded in: `SURREAL-AST-AS-ADAPTER.md` §0 (the carved decision),
16+
> `OGAR-AST-CONTRACT.md` §1 (the canonical IR — `Class` + `ActionDef`
17+
> + `Identity` + `KausalSpec`), `THE-FIREWALL.md` (ADR-022/023 — no
18+
> serialization in the hot path), `ARCHITECTURE.md` (the AR-as-spine
19+
> doctrine).
20+
>
21+
> READ BEFORE: any producer→IR / transcode / codegen / `ogar-from-<lang>`
22+
> reader / `.surql` authoring session. The agent ensemble
23+
> (`core-first-architect`, `adapter-shaper`, `core-gap-auditor`,
24+
> the `Plan` subagent) loads this Tier-1 before output.
25+
26+
## The trap, in one paragraph
27+
28+
You're reading an AR-shaped producer — Ruby callbacks, Odoo
29+
`@api.constrains`, Ecto `Multi`, Elixir `GenStateMachine`, TypeScript
30+
class with decorators. The first reflex is *"I'll walk the structural
31+
DDL form and parse it from there."* That reflex is **System-1** — it
32+
looks like a clean parse step. **System-2** is the harder move: route
33+
through OGAR's `Class` + `ActionDef` first, lift the behavior into
34+
typed fields, *then* emit to SurrealQL (or any other surface) as a
35+
lossy adapter step. The trap is the absence of OGAR — substituting
36+
SurrealQL AST for it. Once you commit to SurrealQL as your primary IR,
37+
the lifecycle has nowhere to go, and the pressure to encode it in
38+
`DEFINE EVENT … WHEN … THEN …` becomes *structural*, not avoidable.
39+
What follows is the negative-beauty hijack the design doc explicitly
40+
rejects: comments, sentinels, DDL pretending to be a state machine.
41+
42+
The trap is silent at the time of writing and loud at the time of
43+
re-derivation. Avoiding it costs five questions. Recovering from it
44+
costs a fork.
45+
46+
## The five questions — run BEFORE the keyboard fires
47+
48+
```
49+
Q1. WHAT am I reading FROM?
50+
├─ Ruby AR / Python @api / Ecto / Elixir GenStateMachine /
51+
│ TypeScript class with decorators / Smalltalk methods / …
52+
│ → HAS BEHAVIOR. Route through a producer-side reader.
53+
54+
└─ SurrealQL DDL / .surql / RDF triples / pure schema /
55+
Avro / JSON Schema / protobuf
56+
→ HAS NO BEHAVIOR to recover. Structural-only is honest.
57+
58+
Q2. Does the source have LIFECYCLE VOCABULARY?
59+
Look for, in order of frequency:
60+
• callbacks before_save / after_commit / after_update
61+
• decorators @api.constrains / @api.depends / @validates
62+
• state machines Statesman / Ecto.Multi / GenStateMachine
63+
• validations validates_presence_of / Zod refine
64+
• lifecycle hooks on_enter / on_exit / state_timeout
65+
• timeout / retry state_timeout_millis / retry-with-backoff
66+
• guards can?(:transition) / GuardFailurePolicy
67+
├─ ANY of the above present → MUST land as ActionDef / KausalSpec.
68+
│ NOT in DDL. Stop reaching for .surql.
69+
└─ NONE present → structural-only is the honest scope.
70+
71+
Q3. What is the TARGET IR I'm about to commit to?
72+
├─ ogar_vocab::Class + ActionDef + Identity + KausalSpec
73+
│ → canonical; behavior has a home. Proceed.
74+
75+
└─ surreal_ast::Library / DefineTable / DefineEvent / .surql files
76+
→ if Q2 was YES, STOP. You're about to hijack DDL.
77+
The target should be OGAR Class FIRST.
78+
Then emit via ogar-adapter-surrealql as a SEPARATE step.
79+
80+
Q4. Which way does my arrow point?
81+
├─ producer → OGAR → adapter(SurrealQL/REST/codegen)
82+
│ → correct. Canonical retains behavior; adapter is lossy
83+
│ egress; the loss is paid once at the boundary, by design.
84+
85+
└─ producer → SurrealQL → ???
86+
→ trap. Behavior loses its home. Pressure to encode
87+
lifecycle in DEFINE EVENT is now structural, not avoidable.
88+
89+
Q5. Would the INVERSE recover the behavior?
90+
Imagine: emit this DDL, hand it to a fresh session, ask them to
91+
distill back to AR. Do they recover ActionDef / lifecycle / guards?
92+
├─ Yes, recoverable → you're smuggling. Behavior is
93+
│ via sentinel comments, hiding in conventions you'll forget
94+
│ hijacked DEFINE EVENT, in 6 months and a reviewer in 2.
95+
│ string-typed state names That IS the trap. Stop.
96+
97+
└─ No, irrecoverable → the behavior was never canonical
98+
from the DDL alone here. Find its real home (Q1's
99+
producer) and read it there.
100+
```
101+
102+
## Diagnostic signatures — what the trap looks like in code review
103+
104+
If you weren't in the room for the decisions, these signatures let you
105+
spot the trap post-hoc:
106+
107+
- **`.surql` files with `DEFINE EVENT … WHEN … THEN …` doing more than
108+
a single row trigger** — chains, conditional cascades, state-name
109+
string literals in the WHEN clause, multi-step transitions
110+
- **`DEFINE FUNCTION` used as a state-machine transition** rather than
111+
a stored procedure (no return value, side-effects on other rows,
112+
reads `state` field and writes a new one)
113+
- **Sentinel comments in DDL**: `-- @action:`, `-- @state:`,
114+
`-- @lifecycle:`, `-- @before_save:`, `-- @kausal:`, `-- @rubicon:`
115+
— any `-- @<vocab-word>` in a DDL file is a smell
116+
- **An IR file named `surreal_ast.rs` / `*_ast.rs` that is the
117+
project's primary producer-side IR** — not an adapter, not a
118+
projection target, *the IR itself*. The name is the tell. Adapters
119+
are named adapters; spines are named IRs.
120+
- **Test files asserting `parse(emit(parse(x))) == parse(x)` for
121+
*behavioral* roundtrips** — structural roundtrips through DDL are
122+
fine (the adapter doc says so); behavioral roundtrips cannot survive
123+
DDL, so the assertion only passes because of hijacked encoding
124+
- **`From<DdlAst> for ActionDef`** / `to_action_def()` /
125+
`extract_lifecycle_from_ddl()` — any function with this shape is
126+
admitting that behavior is being smuggled through DDL
127+
- **String-typed state machines**: `state: "pending" | "committed"`
128+
fields in DDL, with transitions implied by `DEFINE EVENT` triggers
129+
reading those strings
130+
- **A `triple.rs` or `recompute_dag.rs` next to `surreal_ast.rs`**
131+
the colocation pattern of the odoo-rs `od-ontology` fork. If you
132+
see the cluster, the IR has metastasized
133+
134+
A single signature is suspicious; two or more on the same crate is
135+
the trap with high confidence.
136+
137+
## Remediation — if you're already inside
138+
139+
The trap is recoverable, but not by patching. The remediation is
140+
three structural moves; trying to patch in-place re-creates the trap
141+
at a different layer.
142+
143+
1. **Find the original producer.** Whose lifecycle was it really?
144+
Ruby `before_validation`? Odoo `@api.constrains`? Elixir
145+
`GenStateMachine.handle_event`? That source IS the truth — the
146+
DDL is just where its echo materialized. Read the original.
147+
148+
2. **Write an `ogar-from-<lang>` reader** that parses the original
149+
producer (Ruby AST / Python AST / Elixir AST / TypeScript AST)
150+
directly into `Class` + `ActionDef`. Behavior lifts cleanly here;
151+
no sentinels, no DDL hijack. This reader is the new canonical
152+
path — name it for what it does.
153+
154+
3. **Demote the SurrealQL form to egress only.** Keep emitting via
155+
`ogar-adapter-surrealql` (structural arm, lossy on behavior — fine;
156+
the adapter is *meant* to be lossy on the behavioral arm). Delete
157+
the DDL hijacks; they were never canonical, and the canonical reader
158+
from step 2 supersedes them. The fork (if any) collapses to the
159+
adapter call.
160+
161+
odoo-rs is the worked example: W3 of `APP-CODEBOOK-MIGRATION-PLAN.md`
162+
already says this — lower `od-ontology::{surreal_ast,triple,emit}` onto
163+
`ogar_vocab::Class`, emit via the canonical adapter, delete the fork.
164+
The remediation is the migration plan.
165+
166+
## When this doc fires
167+
168+
For **author** sessions (before keyboard):
169+
- Any producer → IR transcode work touching a language with lifecycle
170+
vocabulary (Ruby AR, Python `@api`, Ecto, Elixir, TypeScript classes)
171+
- Any codegen session producing `.surql`, `DEFINE EVENT/FIELD/TABLE`,
172+
`surreal_ast.rs`, or anything named `*_ast.rs` as a *spine*
173+
- Any "distill from SurrealQL" / "lower onto `ogar_vocab::Class`" task
174+
- Any new `ogar-from-<lang>` reader authoring
175+
- Any "behavior-preserving roundtrip" claim involving DDL
176+
177+
For **review** sessions (PR landing):
178+
- Any PR introducing or modifying `.surql` files beyond row-trigger scope
179+
- Any PR adding `From<DdlAst>` / `to_action_def()` conversions
180+
- Any PR claiming `parse(emit(parse(x))) == parse(x)` for behavioral
181+
roundtrips
182+
- Any PR that touches `surreal_ast.rs` / `triple.rs` / `recompute_dag.rs`
183+
in the same crate
184+
185+
For the **agent ensemble**:
186+
- `core-first-architect` (loads at Knowledge Activation Tier-1)
187+
- `adapter-shaper` (loads at Knowledge Activation Tier-1)
188+
- `core-gap-auditor` (loads at Knowledge Activation Tier-1)
189+
- The `Plan` subagent on any task mentioning the trigger phrases above
190+
191+
## Trigger phrases (for Knowledge Activation Protocol)
192+
193+
`SurrealQL AST` · `DDL spine` · `DEFINE EVENT` · `DEFINE FUNCTION` ·
194+
`.surql` · `surreal_ast.rs` · `*_ast.rs` (as IR, not adapter) ·
195+
`distill from SurrealQL` · `lower onto ogar_vocab::Class` ·
196+
`lifecycle in schema` · `from_triples` · `recompute_dag` ·
197+
`producer-side reader` · `behavioral roundtrip`
198+
199+
If the prompt mentions ANY of these, this doc is mandatory pre-read.
200+
201+
## What this doc is NOT
202+
203+
- **Not a ban on `.surql`.** SurrealDB is a real backing store; DDL is
204+
a real interop format; `ogar-adapter-surrealql` is the right emitter.
205+
The trap is using DDL as a *spine*, not as an *adapter*.
206+
- **Not a ban on `DEFINE EVENT`.** Genuine row triggers are fine. The
207+
trap is `DEFINE EVENT` carrying lifecycle / state-machine semantics.
208+
- **Not retroactive.** Code that already lives in the trap (the named
209+
W3 odoo-rs case) doesn't get a citation; it gets the three-move
210+
remediation. Citations are for future sessions.
211+
212+
## Cross-refs
213+
214+
- `docs/SURREAL-AST-AS-ADAPTER.md` — the design decision (the *why*)
215+
- `docs/OGAR-AST-CONTRACT.md` — the canonical IR (the *what*)
216+
- `docs/THE-FIREWALL.md` — the structural reason DDL can't be the spine
217+
(ADR-022/023)
218+
- `docs/ARCHITECTURE.md` — the AR-as-spine doctrine
219+
- `docs/ADAPTERS-AND-ACTORS.md` — the Action / SPO+TeKaMoLo vocabulary
220+
that has no DDL home
221+
- `docs/APP-CODEBOOK-MIGRATION-PLAN.md` W3 — the worked remediation case
222+
(odoo-rs)

0 commit comments

Comments
 (0)