You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
9.8 KiB
262 lines
9.8 KiB
<script lang="ts">
|
|
import Callout from '../../_components/Callout.svelte';
|
|
import CodeBlock from '../../_components/CodeBlock.svelte';
|
|
import PageNav from '../../_components/PageNav.svelte';
|
|
|
|
const readOrder = `1. Read /active/get-started/ecosystem
|
|
2. Read /active/get-started/composition
|
|
3. Read the target module page under /active/docs/<module>
|
|
4. Inspect the real source types before editing:
|
|
- src/libs/<module>/*
|
|
- src/svrs/<module>/* when server authority exists
|
|
- src/arts/<module>/*
|
|
5. Run the smallest relevant test first
|
|
6. Run npm run check before claiming a code change is complete
|
|
7. Run npm run test:all before claiming release-readiness work is complete`;
|
|
|
|
const layerRules = `libs/* → shared contracts, constants and pure helpers
|
|
svrs/* → server authority, ports, backend adapters, secrets
|
|
arts/* → public runtime artifacts and active/client wrappers
|
|
$active-app → client composition root: fixed core plus typed service schema, not server authority`;
|
|
|
|
const importRules = `// Good: modules depend on shared contracts
|
|
import type { Logger } from '$libs/logger';
|
|
|
|
// Good: server authority comes from $svrs
|
|
import { createEngineAuth } from '$svrs/auth';
|
|
import { createEnginePerms } from '$svrs/perm';
|
|
import { createEngineCache } from '$svrs/cache';
|
|
|
|
// Good: active/client wrappers come from $arts aliases
|
|
import { createActiveStorage } from '$storage';
|
|
import { createActiveConnections } from '$connection';
|
|
|
|
// Bad: inventing a per-module logger shape instead of using Logger
|
|
type LocalModuleLogger = Pick<Logger, 'debug'>;`;
|
|
|
|
const activeContract = `interface ActiveEngine<TSnapshot, TError> {
|
|
readonly loading: boolean;
|
|
readonly lastError: TError | null;
|
|
readonly disposed: boolean;
|
|
|
|
snapshot(): TSnapshot;
|
|
clearError(): void;
|
|
onChange(listener: (snapshot: TSnapshot) => void): () => void;
|
|
dispose(): void;
|
|
}`;
|
|
|
|
const constantsRule = `// Good
|
|
export const CONNECTION_LOG_MESSAGES = {
|
|
RECONNECT_SCHEDULED: 'connection.reconnect.scheduled'
|
|
} as const;
|
|
|
|
logger.debug(LOGGER_CATEGORY, CONNECTION_LOG_MESSAGES.RECONNECT_SCHEDULED, {
|
|
context: { name, attempt }
|
|
});
|
|
|
|
// Bad
|
|
logger.debug('connection', 'reconnect scheduled', { name, attempt });`;
|
|
|
|
const completionChecklist = `Before final response:
|
|
- focused tests for the touched module pass
|
|
- npm run check passes
|
|
- npm run test:all passes for release/readiness changes
|
|
- Tests added or updated when behavior changed
|
|
- No invented public API
|
|
- No magic strings for logs/events/errors/protocol methods
|
|
- No new local logger shape when Logger from $libs/logger is enough
|
|
- Server authority remains under $svrs
|
|
- Active/client code does not store secrets or make security decisions
|
|
- Dirty unrelated files were not reverted or formatted`;
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>AI Agents — Active</title>
|
|
</svelte:head>
|
|
|
|
<article class="article">
|
|
<header class="breadcrumbs">
|
|
<a href="/active">Get Started</a>
|
|
<span aria-hidden="true">/</span>
|
|
<span>AI Agents</span>
|
|
</header>
|
|
|
|
<h1>AI agent instructions</h1>
|
|
<p class="lead">
|
|
This page is written for coding assistants that need to modify or extend Active. The goal is
|
|
simple: preserve the ecosystem conventions before touching code.
|
|
</p>
|
|
|
|
<Callout variant="warn" title="Do not improvise the framework">
|
|
<p>
|
|
An AI must not invent factories, logger contracts, event names, routes or server/client
|
|
boundaries. If the public API is unclear, inspect the source types first and update the
|
|
documentation after the code is corrected.
|
|
</p>
|
|
</Callout>
|
|
|
|
<h2>Required reading order</h2>
|
|
<p>
|
|
Before editing a module, read the ecosystem and composition pages, then the concrete module
|
|
page. Documentation is guidance, but source types are the final authority.
|
|
</p>
|
|
<CodeBlock code={readOrder} lang="text" />
|
|
|
|
<h2>Layer rules</h2>
|
|
<p>
|
|
The most common AI failure is mixing layers. Keep the four layers separate:
|
|
</p>
|
|
<CodeBlock code={layerRules} lang="text" />
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Question</th>
|
|
<th>Correct layer</th>
|
|
<th>Reason</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>Is this a constant, type or pure helper?</td><td><code>libs</code></td><td>Shared by server, active and tests.</td></tr>
|
|
<tr><td>Does this decide identity, access or private cache scope?</td><td><code>svrs</code></td><td>The server is authoritative.</td></tr>
|
|
<tr><td>Does this expose Svelte state or browser UX?</td><td><code>arts</code></td><td>Active wrappers live in <code>.svelte.ts</code>.</td></tr>
|
|
<tr><td>Does this wire existing modules for the app?</td><td><code>$active-app</code></td><td>Composition, not new domain logic.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2>Import rules</h2>
|
|
<p>
|
|
Use the established aliases and shared contracts. Do not create a new interface just because
|
|
a function only needs one logger method today.
|
|
</p>
|
|
<CodeBlock code={importRules} lang="ts" />
|
|
|
|
<h2>Factories</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Meaning</th>
|
|
<th>Where</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td><code>createEngineXxx</code></td><td>Imperative/pure runtime, no Svelte state.</td><td><code>arts</code> or <code>svrs</code>, depending on authority.</td></tr>
|
|
<tr><td><code>createActiveXxx</code></td><td>Reactive Svelte wrapper over runtime state.</td><td><code>arts/*/*.svelte.ts</code>.</td></tr>
|
|
<tr><td><code>defineActiveXxx</code> / <code>defineEngineXxx</code></td><td>Service-schema factory for App composition.</td><td><code>$active-app/services</code>.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<Callout variant="info" title="Server-backed modules">
|
|
<p>
|
|
<code>auth</code>, <code>perm</code> and <code>cache</code> have server modules under
|
|
<code>$svrs</code>. Their active modules are client reflectors. Do not move
|
|
authoritative logic into active/browser code.
|
|
</p>
|
|
</Callout>
|
|
|
|
<h2>Active contract</h2>
|
|
<p>
|
|
If a module exposes reactive state, keep the shared <code>ActiveEngine</code> shape. Do not
|
|
rename <code>loading</code> to <code>pending</code>, do not hide state under an arbitrary
|
|
<code>state</code> object, and make <code>dispose()</code> real.
|
|
</p>
|
|
<CodeBlock code={activeContract} lang="ts" />
|
|
|
|
<h2>Logging and diagnostics</h2>
|
|
<p>
|
|
Every module receives the minimal <code>Logger</code> contract from <code>$libs/logger</code>.
|
|
Diagnostics are allowed as a catalog layer, but diagnostics emit normal logger calls. Do not
|
|
create module-local logger contracts or aliases unless there is a documented integration
|
|
reason.
|
|
</p>
|
|
<CodeBlock code={constantsRule} lang="ts" />
|
|
|
|
<ul>
|
|
<li>Logger categories, messages and diagnostic event names must be constants.</li>
|
|
<li>Do not hard-code logger strings inside implementation bodies.</li>
|
|
<li>Do not couple every module to <code>$logger</code>; depend on <code>$libs/logger</code> for the contract.</li>
|
|
<li>EngineLogger is the implementation; Logger is the dependency accepted by modules.</li>
|
|
</ul>
|
|
|
|
<h2>Security rules</h2>
|
|
<ul>
|
|
<li><code>auth</code> proves identity; <code>session</code> keeps continuity; <code>perm</code> decides access.</li>
|
|
<li>The browser never decides authorization. ActivePerms is UX only.</li>
|
|
<li>Storage must not persist passwords, refresh tokens, OTPs, CSRF secrets or provider tokens.</li>
|
|
<li>Private cache entries must include actor, tenant or permission scope when session/permission data exists.</li>
|
|
<li>Server routes must resolve actor context from server session, not from request body.</li>
|
|
</ul>
|
|
|
|
<h2>Documentation rules</h2>
|
|
<p>
|
|
Do not write aspirational docs as if the API exists. If a method is future/planned, mark it
|
|
as such or leave it out. Docs must match exports and types.
|
|
</p>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>When documenting...</th>
|
|
<th>Verify against</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>Factories and exports</td><td><code>src/arts/<module>/index.ts</code>, <code>src/svrs/<module>/index.ts</code></td></tr>
|
|
<tr><td>Options and methods</td><td><code>types.ts</code> and implementation return objects.</td></tr>
|
|
<tr><td>Server behavior</td><td><code>src/svrs/*</code>, not the active client.</td></tr>
|
|
<tr><td>Examples</td><td>Existing tests or a compiled TypeScript snippet.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2>Change checklist</h2>
|
|
<CodeBlock code={completionChecklist} lang="text" />
|
|
|
|
<Callout variant="info" title="Gate vocabulary">
|
|
<p>
|
|
Use <code>npm run check</code> for type and Svelte diagnostics, <code>npm test</code>
|
|
for the Vitest suite, <code>npm run build</code> for static output,
|
|
<code>npm run test:static</code> for generated route/assets smoke, and
|
|
<code>npm run test:bundle</code> for the <code>createActiveApp({})</code>
|
|
bundle budget. <code>npm run test:all</code> is the combined release-readiness gate.
|
|
</p>
|
|
</Callout>
|
|
|
|
<h2>Suggested audit prompt</h2>
|
|
<p>
|
|
When asking another AI to audit the project, give it this framing so it reviews the system
|
|
through the same conventions:
|
|
</p>
|
|
<CodeBlock
|
|
lang="text"
|
|
code={`Audit this Active framework module against its ecosystem rules:
|
|
|
|
- Verify public docs match real exports and types.
|
|
- Check layer boundaries: libs vs svrs vs arts vs active-app.
|
|
- Find magic strings in logs, events, errors, methods, protocol messages and routes.
|
|
- Check logger usage: modules should accept Logger from $libs/logger.
|
|
- Verify ActiveEngine consistency: loading, lastError, disposed, snapshot, clearError, onChange, dispose.
|
|
- Verify server authority for auth, perm and cache.
|
|
- Identify duplicated boilerplate, oversized files, missing constants and missing tests.
|
|
- Do not propose new APIs without showing where they fit in the existing conventions.
|
|
- Write findings with file paths, severity, rationale and concrete remediation.`}
|
|
/>
|
|
|
|
<PageNav />
|
|
</article>
|
|
|
|
<style>
|
|
.breadcrumbs {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.4rem;
|
|
font-size: 0.8125rem;
|
|
color: var(--c-fg-subtle);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.breadcrumbs a {
|
|
color: var(--c-fg-muted);
|
|
}
|
|
</style>
|