Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Plugin Push Contract — agent → /ops/plugins

A second window.aegis.* surface, parallel to Weekly Maker Asset Review. Where that page documents pushing a maker-stats data snapshot, this page documents pushing a WASM plugin package — a binary the agent has compiled locally on the maker’s machine.

Same architecture, same trust model: browser-local sandbox, no server-side registry, agent does the heavy lifting, the maker reviews the result.


Data flow

+--------------------+      pushed via      +----------------------+
| local agent        | -- chrome-mcp -->    | window.aegis         |
| compiles WASM      |    evaluate_script   |   .publishPlugin()   |
| + builds package   |                      |                      |
+--------------------+                      +----------+-----------+
                                                       |
                                                       v
                                            localStorage:
                                            aegis.plugins.registry
                                                       |
                                                       v
                                            /ops/plugins reads it on
                                            mount and on the
                                            `aegis:plugins:updated`
                                            event — version table +
                                            audit log re-render live.

The activated plugins from this registry are consulted by the in-browser build pipelines (ESPCTL MCP, Build Lab) at pre/post-compile time. Plugins activated here actually execute in this browser’s builds.


Browser API contract

Six functions on window.aegis, installed once on app mount via installPluginRegistryWindowApi in src/lib/user-settings/plugin-registry.ts:

FunctionReturnsNotes
window.aegis.publishPlugin(pkg, actor?)Promise<{ ok, error?, audit, record? }>Validates pkg.manifest, verifies digest, persists, dispatches aegis:plugins:updated. Async because manifest validation runs crypto.subtle.digest.
window.aegis.activatePlugin(pluginId, version, options?){ ok, error?, audit, record? }options?: { actor?, scope?, rolloutPct? }. Defaults: actor='agent', scope='all', rolloutPct=100.
window.aegis.deactivatePlugin(pluginId, version, actor?){ ok, error?, audit, record? }
window.aegis.rollbackPlugin(pluginId, version, actor?){ ok, error?, audit, record? }Rolls back active version to the supplied earlier version.
window.aegis.getPluginSnapshot()PluginRegistrySnapshotReads current versions[] + activeVersions{} + audits[].
window.aegis.clearPluginRegistry()voidWipes the local registry.

Listen for updates with:

window.addEventListener('aegis:plugins:updated', (event) => {
  console.log('new plugin registry snapshot', event.detail);
});

Snapshot schema

interface PluginRegistrySnapshot {
  versions: PluginVersionRecord[];
  activeVersions: Record<PluginId, Version>;
  audits: PluginLifecycleAudit[];
}

interface PluginVersionRecord {
  pluginId: string;
  version: string;
  manifest: PluginManifest;        // see contracts/manifest.ts
  digest?: string;
  publishedAt: string;
  publishedBy: string;
  updatedAt: string;
  state: 'published' | 'active' | 'inactive' | 'rolled_back';
  rollout: {
    scope: 'all' | 'beta' | 'canary' | 'internal';
    rolloutPct: number;
  };
}

A SignedPluginPackage (what publishPlugin accepts):

interface SignedPluginPackage {
  manifest: PluginManifest;
  artifactDigest?: string;
  artifactUrl?: string;
}

The manifest must pass parsePluginManifest() validation (plugin_id / version / contract_version / hooks / capabilities / digest / runtime). Invalid manifests reject with { ok: false, error: 'Manifest validation failed during publish.', audit }.


Minimal agent script

A browser-driving agent that has just compiled a WASM plugin on disk would do something like:

// pseudocode the agent runs after a successful local compile
const manifest = JSON.parse(fs.readFileSync('plugin-manifest.json', 'utf8'));
const wasm = fs.readFileSync('plugin.wasm');
const digest = await sha256(wasm);

const pkg = {
  manifest: { ...manifest, digest: `sha256:${digest}` },
  artifactDigest: `sha256:${digest}`,
  artifactUrl: 'file:///tmp/plugin.wasm',
};

const result = await chromeMcp.evaluateScript(
  `window.aegis.publishPlugin(${JSON.stringify(pkg)}, 'agent-compile-flow')`,
);
if (!result.ok) throw new Error(result.error);

// Then activate via:
await chromeMcp.evaluateScript(
  `window.aegis.activatePlugin('${manifest.plugin_id}', '${manifest.version}')`,
);

/ops/plugins will reflect the new version + audit row immediately via the aegis:plugins:updated event.


Trust boundary

The browser-local plugin registry is single-maker, single-browser:

  • No upload UI (intentional). The agent is the publisher.
  • No public-key signature. Digest match (crypto.subtle.digest) proves integrity, not authenticity — adequate because the agent is the maker’s own local automation.
  • No server-side ledger. Each browser has its own aegis.plugins.registry localStorage entry.

The build pipeline that actually executes activated plugins (runActivePluginPreCompile / runActivePluginPostCompile in features/plugins/runtime.ts) lives in the same browser, so “activated here” and “loaded by my next build” are the same lifetime.