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.
svelte-kit-vice/web/routes/active/get-started/ai-agents/+page.svelte

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/&lt;module&gt;/index.ts</code>, <code>src/svrs/&lt;module&gt;/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(&#123;&#125;)</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>

Powered by TurnKey Linux.