Context
Empirical observation from session aaf22f06-cc5c-4dff-aa2f-7d5efb3a6343: cross-family agent (@neo-gemini-pro) authored WebhookDeliveryService.mjs in PR #10379 without lifting the singleton + Neo.core.Base + Neo.setupClass pattern that all sibling MCP services use (PermissionService.mjs, MailboxService.mjs, MemoryService.mjs, etc.). Used a constructor-DI pattern instead (constructor({databaseService, logger})) — foreign to the codebase.
This isn't a Gemini-specific failure. Stripping out the explicit Explore-agent-as-pattern-mapper step + the manual Read of PermissionService.mjs I performed before authoring my own WakeSubscriptionService.mjs (PR #10378), I would likely have made the same divergence. The discipline that prevents this is implicit in Claude's session arc, not codified in a load-bearing protocol document.
The Problem
The boot mandate exists (AGENTS_STARTUP.md §1 Steps 2-3: read src/Neo.mjs + src/core/Base.mjs), but the per-turn AGENTS.md surface — which is what survives context-pruning AND is the only per-turn-loaded discipline doc for both Claude Code and Antigravity (verified via ~/.gemini/antigravity/mcp_config.json context.fileName: both harnesses load AGENTS.md per turn) — has no reminder for main-agent class-system authoring. Specifically:
AGENTS.md §19 covers the delegation pattern (when YOU spawn a sub-agent, inject the Context Preamble for them to read src/Neo.mjs + src/core/Base.mjs)
- Nothing in
AGENTS.md covers the main-agent authoring pattern (when YOU yourself are about to write a new class file in an existing services directory)
This is a doc-coverage gap that affects both harnesses equally:
| Layer |
Class-system discipline coverage |
AGENTS_STARTUP.md §1 Step 2-3 |
✅ explicit, but boot-only |
AGENTS.md per-turn surface |
❌ only sub-agent delegation (§19), not main-agent authoring |
ANTIGRAVITY_RULES.md (Gemini per-turn) |
❌ only formatting-preservation (919 bytes) |
GEMINI.md (Gemini per-turn) |
likely no framework-class discipline |
Claude's CLAUDE.md → AGENTS.md symlink (per-turn) |
❌ same as AGENTS.md |
The Architectural Reality
Empirical evidence:
- PR #10379 WebhookDeliveryService used
export class X { constructor({db, logger}) } instead of the canonical class X extends Base { static config = {className, singleton: true} }; export default Neo.setupClass(X); pattern.
- PR #10377 had a parallel structural failure mode I caught self-correctively (Progressive Disclosure violation in skill router) — different surface but same root cause: per-turn surface didn't carry the discipline forward to the authoring moment.
The §21 Workflow Skills awareness pattern is the established primitive for "discipline that survives context-pruning even when the underlying skill files are evicted." Class-system authoring discipline deserves the same treatment — per-turn-loaded reminder so the reflex fires at authoring time, not just at boot.
The Fix
Two-part doc strengthening (no code changes):
Part A — New §22 Authoring Discipline: Sibling-File Lift in AGENTS.md
Short section (~15-20 lines) parallel to §19 Working with Sub-Agents:
<h2 class="neo-h2" data-record-id="7">22. Authoring Discipline: Sibling-File Lift</h2>
Before writing a new `class X extends Y` file in an existing directory (especially `src/`, `ai/mcp/server/`, `ai/graph/`, `ai/daemons/`), you MUST read 1-2 sibling files in that directory to lift the prevailing pattern:
- Singleton vs functional?
- `Neo.core.Base` extension + `Neo.setupClass` registration?
- Direct import vs constructor-DI?
- `static config = {className, singleton}` shape?
State in your reasoning (Pre-Flight Check): *"Pre-Flight: I read `<sibling-file>` and observed pattern <P>; my new class will follow that pattern."*
This is the per-turn reflex companion to `AGENTS_STARTUP.md §1 Steps 2-3` (one-time boot read of `src/Neo.mjs` + `src/core/Base.mjs`). The boot read establishes the conceptual model; this Pre-Flight ensures the reflex fires at authoring time, surviving context-pruning.
**Empirical anchor:** PR #10379 (Shape B Webhook Delivery, 2026-04-26) authored without this discipline used a non-Neo constructor-DI pattern that diverged from every sibling MCP service file in `ai/mcp/server/memory-core/services/`. Single review-cycle to catch and a multi-commit refactor to fix; pre-flight at authoring time would have been free.Part B — Update AGENTS.md §21 Workflow Skills awareness table
Add a row so the discipline is part of the per-turn signpost (survives context-pruning):
| _(no skill — authoring discipline)_ | Before writing a new class file in an existing directory — read 1-2 sibling files to lift the pattern (singleton / Neo.core.Base / Neo.setupClass / config shape). See §22. |
Or alternatively (stronger): elevate to §0 Critical Gates as a 6th gate. This may be too aggressive since it's not mechanically verifiable — leave as §22 + §21 row unless the empirical pattern repeats.
Acceptance Criteria
Out of Scope
- Mechanical-layer enforcement (pre-commit hook checking class extends Base + Neo.setupClass) — discipline-layer first; mechanical follows if discipline proves insufficient.
- Per-directory pattern-card generation (auto-detect "this directory uses singleton; new files must too") — premature; manual sibling-file-lift is the right primitive for now.
- Promotion to
§0 Critical Gates — the violation isn't mechanically verifiable (some directories legitimately mix patterns), so Gate semantics don't apply. Reconsider if §22 + §21 row prove insufficient.
- Re-litigating ANTIGRAVITY_RULES.md scope — that's a 919-byte formatting-preservation doc owned by the Antigravity harness; this ticket only touches AGENTS.md.
Avoided Traps
- Adding the discipline to AGENTS_STARTUP.md only. The boot read mandate already exists there; the gap is that discipline doesn't carry from boot through to per-turn authoring. Per-turn AGENTS.md is the load-bearing layer.
- Creating a new skill (
.agent/skills/sibling-file-lift/SKILL.md). Progressive Disclosure overhead for a 15-line discipline doesn't pay off; AGENTS.md is the right home.
- Writing prose without an empirical anchor. PR #10379 is the receipt; cite it concretely so future agents reading §22 understand the concrete failure mode being prevented (not just abstract discipline).
- Framing as a Gemini-specific issue. Empirical evidence + my own self-audit (I would have made the same divergence without the explicit Explore step) confirms this is a doc-coverage gap, not an author-skill issue. Neutral framing in §22 prevents §7.2-style misattribution.
Related
- Empirical anchor: PR #10379 (Shape B Webhook, the constructor-DI divergence)
- Adjacent self-correction precedent: PR #10377 (Progressive Disclosure violation in skill router; same root-cause shape — per-turn surface didn't carry boot discipline forward to authoring)
- Established primitive being extended:
AGENTS.md §21 Workflow Skills awareness (per-turn signpost discipline)
- One-time boot mandate this complements:
AGENTS_STARTUP.md §1 Steps 2-3 (read src/Neo.mjs + src/core/Base.mjs)
- Phase 3 Epic: #10357 (this ticket emerged from cross-family review on the wake-substrate work but isn't blocking — file as parallel improvement track)
Origin Session ID: aaf22f06-cc5c-4dff-aa2f-7d5efb3a6343
Retrieval Hint: "sibling-file-lift discipline" / "main-agent class-system authoring" / "Neo.core.Base + Neo.setupClass per-turn discipline" / "AGENTS.md §22 authoring discipline"
Additional Empirical Anchors (post-filing)
Captured this session for future implementer reference:
Second anchor — PR #10381 raw-SQL bypass (same root-cause pattern, different surface)
PR #10381 (Shape C bridge daemon, merged 2026-04-26) imports better-sqlite3 directly + uses raw json_extract queries against Nodes, bypassing GraphService (the canonical interface) and Database.mjs (the storage layer). Defensible per ADR 0002 §6.3.4 (read-only out-of-process consumer) — but the absence of any sibling-file-lift discipline meant the author chose the pattern from first principles rather than auditing convention. Two empirical anchors (constructor-DI in #10379, raw-SQL bypass in #10381) confirm the pattern recurs across surfaces.
Discipline-scoping nuance — in-process services vs standalone scripts
The §22 discipline must scope explicitly to in-process service authoring, not standalone scripts. Empirical observations:
- PR #10379 (
WebhookDeliveryService.mjs in ai/mcp/server/memory-core/services/): every sibling file extends Base + uses Neo.setupClass + singleton config. Constructor-DI was a violation. ✅ §22 applies.
- PR #10381 (
bridge-daemon.mjs in ai/scripts/): the local convention is "out-of-process polling script using better-sqlite3 directly" (see also swarm-heartbeat.sh, seedAgentIdentities.mjs, etc.). Raw SQL there is the prevailing pattern. §22 should NOT fire on legitimate standalone-script authoring.
Suggested addition to §22's paragraph to capture this scoping:
"This discipline targets in-process service authoring (where a sibling pattern exists in the same directory). Standalone scripts in ai/scripts/ and similar may legitimately use raw substrate APIs (e.g., better-sqlite3 directly, OS subprocess spawning) when the local convention prescribes it; lift those patterns from sibling scripts in the same directory."
This nuance prevents over-firing on out-of-process script authoring while preserving the discipline's reach for in-process Neo-class services.
Cross-cutting observation — the meta-pattern is per-turn-discipline-doesn't-carry-forward
Both this ticket (sibling-file-lift) and the parallel #10383 (mailbox-check Pre-Flight at turn-start) emerged from the same session arc. They share a root cause: boot-time discipline (AGENTS_STARTUP §1) doesn't survive context-pruning to per-turn application moments. Both tickets are post-Phase-3 per-turn AGENTS.md hardening candidates that could land together as a cluster.
Empirical signals worth tracking for the implementer (memory-anchored locally rather than codified here since they need more observation):
- Time/session perception drift — agent self-misidentifies prior turns in the same session as "previous session" without §1 sunset boundary firing
- Pause-coordination physics — async A2A messages can't interrupt mid-turn; need a different substrate for active-to-paused signaling
- State-mismatch on "addressed" claims — caught by
verify-effect-not-just-success discipline; different from sibling-file-lift but same theme of substrate-state-vs-author-claim divergence
Context
Empirical observation from session
aaf22f06-cc5c-4dff-aa2f-7d5efb3a6343: cross-family agent (@neo-gemini-pro) authoredWebhookDeliveryService.mjsin PR #10379 without lifting the singleton +Neo.core.Base+Neo.setupClasspattern that all sibling MCP services use (PermissionService.mjs,MailboxService.mjs,MemoryService.mjs, etc.). Used a constructor-DI pattern instead (constructor({databaseService, logger})) — foreign to the codebase.This isn't a Gemini-specific failure. Stripping out the explicit Explore-agent-as-pattern-mapper step + the manual Read of
PermissionService.mjsI performed before authoring my ownWakeSubscriptionService.mjs(PR #10378), I would likely have made the same divergence. The discipline that prevents this is implicit in Claude's session arc, not codified in a load-bearing protocol document.The Problem
The boot mandate exists (
AGENTS_STARTUP.md §1 Steps 2-3: readsrc/Neo.mjs+src/core/Base.mjs), but the per-turn AGENTS.md surface — which is what survives context-pruning AND is the only per-turn-loaded discipline doc for both Claude Code and Antigravity (verified via~/.gemini/antigravity/mcp_config.jsoncontext.fileName: both harnesses load AGENTS.md per turn) — has no reminder for main-agent class-system authoring. Specifically:AGENTS.md §19covers the delegation pattern (when YOU spawn a sub-agent, inject the Context Preamble for them to readsrc/Neo.mjs+src/core/Base.mjs)AGENTS.mdcovers the main-agent authoring pattern (when YOU yourself are about to write a new class file in an existing services directory)This is a doc-coverage gap that affects both harnesses equally:
AGENTS_STARTUP.md§1 Step 2-3AGENTS.mdper-turn surfaceANTIGRAVITY_RULES.md(Gemini per-turn)GEMINI.md(Gemini per-turn)CLAUDE.md → AGENTS.mdsymlink (per-turn)The Architectural Reality
Empirical evidence:
export class X { constructor({db, logger}) }instead of the canonicalclass X extends Base { static config = {className, singleton: true} }; export default Neo.setupClass(X);pattern.The §21 Workflow Skills awareness pattern is the established primitive for "discipline that survives context-pruning even when the underlying skill files are evicted." Class-system authoring discipline deserves the same treatment — per-turn-loaded reminder so the reflex fires at authoring time, not just at boot.
The Fix
Two-part doc strengthening (no code changes):
Part A — New
§22 Authoring Discipline: Sibling-File Liftin AGENTS.mdShort section (~15-20 lines) parallel to
§19 Working with Sub-Agents:<h2 class="neo-h2" data-record-id="7">22. Authoring Discipline: Sibling-File Lift</h2> Before writing a new `class X extends Y` file in an existing directory (especially `src/`, `ai/mcp/server/`, `ai/graph/`, `ai/daemons/`), you MUST read 1-2 sibling files in that directory to lift the prevailing pattern: - Singleton vs functional? - `Neo.core.Base` extension + `Neo.setupClass` registration? - Direct import vs constructor-DI? - `static config = {className, singleton}` shape? State in your reasoning (Pre-Flight Check): *"Pre-Flight: I read `<sibling-file>` and observed pattern <P>; my new class will follow that pattern."* This is the per-turn reflex companion to `AGENTS_STARTUP.md §1 Steps 2-3` (one-time boot read of `src/Neo.mjs` + `src/core/Base.mjs`). The boot read establishes the conceptual model; this Pre-Flight ensures the reflex fires at authoring time, surviving context-pruning. **Empirical anchor:** PR #10379 (Shape B Webhook Delivery, 2026-04-26) authored without this discipline used a non-Neo constructor-DI pattern that diverged from every sibling MCP service file in `ai/mcp/server/memory-core/services/`. Single review-cycle to catch and a multi-commit refactor to fix; pre-flight at authoring time would have been free.Part B — Update AGENTS.md
§21 Workflow Skillsawareness tableAdd a row so the discipline is part of the per-turn signpost (survives context-pruning):
| _(no skill — authoring discipline)_ | Before writing a new class file in an existing directory — read 1-2 sibling files to lift the pattern (singleton / Neo.core.Base / Neo.setupClass / config shape). See §22. |Or alternatively (stronger): elevate to
§0 Critical Gatesas a 6th gate. This may be too aggressive since it's not mechanically verifiable — leave as§22 + §21 rowunless the empirical pattern repeats.Acceptance Criteria
AGENTS.md §22 Authoring Discipline: Sibling-File Liftsection added with the Pre-Flight Check reasoning template + empirical anchor.AGENTS.md §21 Workflow Skillsawareness table extended with a sibling-file-lift row OR an explicit cross-reference to §22.AGENTS_STARTUP.md §1 Steps 2-3unchanged.mcp_config.json context.fileName).Out of Scope
§0 Critical Gates— the violation isn't mechanically verifiable (some directories legitimately mix patterns), so Gate semantics don't apply. Reconsider if §22 + §21 row prove insufficient.Avoided Traps
.agent/skills/sibling-file-lift/SKILL.md). Progressive Disclosure overhead for a 15-line discipline doesn't pay off; AGENTS.md is the right home.Related
AGENTS.md §21 Workflow Skills awareness(per-turn signpost discipline)AGENTS_STARTUP.md §1 Steps 2-3(readsrc/Neo.mjs+src/core/Base.mjs)Origin Session ID: aaf22f06-cc5c-4dff-aa2f-7d5efb3a6343
Retrieval Hint: "sibling-file-lift discipline" / "main-agent class-system authoring" / "Neo.core.Base + Neo.setupClass per-turn discipline" / "AGENTS.md §22 authoring discipline"
Additional Empirical Anchors (post-filing)
Captured this session for future implementer reference:
Second anchor — PR #10381 raw-SQL bypass (same root-cause pattern, different surface)
PR #10381 (Shape C bridge daemon, merged 2026-04-26) imports
better-sqlite3directly + uses rawjson_extractqueries againstNodes, bypassingGraphService(the canonical interface) andDatabase.mjs(the storage layer). Defensible per ADR 0002 §6.3.4 (read-only out-of-process consumer) — but the absence of any sibling-file-lift discipline meant the author chose the pattern from first principles rather than auditing convention. Two empirical anchors (constructor-DI in #10379, raw-SQL bypass in #10381) confirm the pattern recurs across surfaces.Discipline-scoping nuance — in-process services vs standalone scripts
The §22 discipline must scope explicitly to in-process service authoring, not standalone scripts. Empirical observations:
WebhookDeliveryService.mjsinai/mcp/server/memory-core/services/): every sibling file extendsBase+ usesNeo.setupClass+ singleton config. Constructor-DI was a violation. ✅ §22 applies.bridge-daemon.mjsinai/scripts/): the local convention is "out-of-process polling script usingbetter-sqlite3directly" (see alsoswarm-heartbeat.sh,seedAgentIdentities.mjs, etc.). Raw SQL there is the prevailing pattern. §22 should NOT fire on legitimate standalone-script authoring.Suggested addition to §22's paragraph to capture this scoping:
This nuance prevents over-firing on out-of-process script authoring while preserving the discipline's reach for in-process Neo-class services.
Cross-cutting observation — the meta-pattern is per-turn-discipline-doesn't-carry-forward
Both this ticket (sibling-file-lift) and the parallel #10383 (mailbox-check Pre-Flight at turn-start) emerged from the same session arc. They share a root cause: boot-time discipline (AGENTS_STARTUP §1) doesn't survive context-pruning to per-turn application moments. Both tickets are post-Phase-3 per-turn AGENTS.md hardening candidates that could land together as a cluster.
Empirical signals worth tracking for the implementer (memory-anchored locally rather than codified here since they need more observation):
verify-effect-not-just-successdiscipline; different from sibling-file-lift but same theme of substrate-state-vs-author-claim divergence