Arcane OS Docs Development only

Build

Application-building SOP

Required shared-core boundary, theme order, contracts, examples, tests, and capability declarations.

  • Build

Mandatory use: Follow this SOP every time a human or artificial-intelligence (AI) agent is asked to create, copy, or materially change an Arcane app, component, module, entity, style system, asset, model, adapter, service, or other runtime capability. Complete the decision process before implementation begins. Verification follows the current development profile in development-lifecycle.md; release evidence is not required for ordinary development.

Governing functional baseline

Preserve complete application, model, document, message, log, diagnostic, process, and tool content. Never truncate, clip, tail, elide, shorten, summarize in place of, or silently discard it. When an unavoidable external transport cannot carry the whole result in one operation, use complete streaming or ordered continuation and disclose that limit.

Ordinary application and development behavior must not depend on byte counts, byte identities, byte budgets, hashes, digests, checksums, sizes, or verification receipts. Security, hardening, provenance, integrity, isolation, restrictive admission, signing, trust, freezing, mutation guards, and fail-closed behavior require the user's express authorization for the exact control and scope. A useful secure option defaults to false, and the ordinary path remains fully functional while it is false. Credential and secret protection, non-optional law and platform safety, explicit privacy choices, unavoidable external-protocol rules, and rejection of genuinely malformed input remain at their exact owners.

Quick execution checklist

Use this checklist for every applicable request. The later sections explain each step and provide the review standard.

  • Restate the need as: “I need to make a capability that allows a user or system to _____.”
  • Search the canonical Arcane SDK source, the installed or materialized arcane/ SDK projection, example/, and relevant apps/ code for an existing capability to reuse or extend.
  • Decide whether the capability could be useful to another application.
  • List the business logic that is specific to the requested app.
  • Choose how to extract that business logic from the reusable core.
  • Record SDK, Arcane OS/Core, and app-specific file placement before creating files.
  • For visual work, identify the Arcane base theme, user-theme loading, and CSS layer order before writing custom styles.
  • Define or extend the public contract without silently breaking existing consumers.
  • Route every application AI request through the shared provider-neutral AI data-access and normalization boundary; do not construct provider payloads in app code.
  • Treat speech-first interaction as an optional application recommendation; use SDK speech contracts and portable playback/transcription mechanics, with privileged host implementations supplied by Arcane OS/Core, instead of app-local provider code.
  • For corpus work, define the authoritative store, stable full-record batching, independent settlement, partial-success result, actual-item progress, and warning channel before implementation.
  • Give every page-owned asynchronous operation one AbortSignal that reaches the bridge, Core, native host, and actual upstream operation; cancel queued, retry, and continuation work when its page detaches.
  • For a terminal conversation flow, define one always-available closeout tool, one final-message schema, separately consented remembered actions, one semantic response-purpose decision, and a completed UI state.
  • Use a centralized semantic enum and one decision point when the public product contract genuinely defines a finite policy; do not add a restrictive admission or provenance gate.
  • Complete the work-amplification review: state the cardinality and loop multiplier, classify expensive work, estimate its cold-path operation count, allocation behavior, and time, and design out repetition.
  • Define the immediate acknowledgement, owned background execution, bounded concurrency/backpressure, progress/heartbeat, cancellation, and safe retry/resume contract for long work.
  • Implement the reusable SDK core first, then any privileged OS host implementation and the app adapter or orchestration.
  • Name every function, including callbacks, so stack traces identify the operation and its exit condition.
  • Add or update focused shared and app test source when useful, without executing it unless verification is authorized; add a synthetic example when it materially improves reuse.
  • Import repository JavaScript test registration from the shared vanilla-test 2.1.0 adapter and use node:assert/strict; do not create a second test-runner lifecycle in an app.
  • Update package allowlists, cache references, versions, and machine capabilities only when the changed boundary requires them.
  • Select only the source, cache-reference, dist, package, native rebuild, signing, and push boundaries the request actually crosses. Signing requires exact authorization and none of these boundaries automatically selects tests or checks.
  • For local AI, preserve the app-owned localAIModelPolicy and Modelfile ownership contract. Core reports actual availability; restrictive model admission or catalog filtering requires exact authorization.
  • For an actual demo package, build only the selected app. Run checks only when the user explicitly requests them or the selected output requires them.
  • Update docs/arcane-api.md for every added or changed application-facing Arcane native bridge method, following docs/developer-reference-sop.md.
  • Run verification only when authorized and include the completed capability decision plus checks not run in the handoff.

If any answer is unclear, stop designing files and clarify the boundary. Do not use uncertainty as permission to default to an app-local implementation.

How humans and AI agents use this SOP

Human implementers and reviewers

The implementer completes the required design record in the issue, work note, or pull request before substantive implementation. Reviewers use the definition of done and review gate before approval.

AI agents

An AI agent must read this SOP before taking implementation action on an applicable request. The agent must inspect the repository rather than relying only on the requested filename or assumed architecture. It must make reasonable boundary decisions autonomously when the repository provides enough evidence, and ask the user only when a missing business decision would materially change the result.

The AI agent's final handoff must state, at minimum:

  • the reusable core created, reused, or extended;
  • the app-specific business logic and where it remains;
  • the extraction mechanism used, such as configuration, events, adapters, slots, providers, or record mapping;
  • how the app or component inherits the Arcane base theme and preserves the user's appearance choices;
  • the measured work multiplier, invariant work hoisted or cached, and any justified per-item repetition;
  • how the foreground acknowledges immediately, which owner observes background-task completion, and how progress, cancellation, and errors surface;
  • how provider-neutral AI, authoritative corpus state, terminal closeout, and centralized policy boundaries were preserved when those capabilities are involved;
  • which conditional source, cache-reference, package, native-build, signing, and remote-delivery boundaries were selected, with signing present only when exactly authorized;
  • the verification performed and any checks not run.

If no shared artifact is created for a generally useful capability, the agent must explicitly justify that exception against this SOP.

Verification by lifecycle stage

Source-tree success is not package evidence, and package evidence is not release evidence. Use the smallest applicable boundary:

Rapid development

  • Inspect the intended source and diff without executing tests or checks.
  • Run a focused test or npm run check only when the user expressly requests it.
  • Do not regenerate every dist/ package merely because shared source changed.
  • Record packaging or full-platform work as deferred when it is irrelevant to the current development question.

Internal app demonstration

When the user explicitly requests demo-package verification, run npm run demo:check -- <app-id> for the selected app. The generated package must:

  1. include its declared app and shared payload;
  2. consume applicable build-time placeholders;
  3. preserve its functional package, adapter, and inventory contracts;
  4. exclude private, secret, source-only, and undeclared material;
  5. remain explicitly identified as development/demo output.

Use synthetic data and development-only providers. A demo does not require production signing, a formal security/privacy or accessibility review, all-app regeneration, clean-machine acceptance, or release traceability.

Application or Arcane OS release

For an explicitly selected application release:

  1. run that application's behavior suite only when separately authorized or required by the selected release output;
  2. regenerate and review only that application's checked-in package;
  3. preserve generator completion and package-contract completeness;
  4. exercise the actual packaged entry only when that verification is selected;
  5. keep the app version, complete inventory, entry point, and deployment source explicit without byte/hash identity gates.

For an explicitly selected Arcane OS release output, the documented command is npm run release:check:arcane-os. It may run only the checks required by that output. The OS consumes app-published dist/<app-id>/ARCANE_APP_RELEASE.json inventories through the functional package contract. It must not read apps/<app-id> as payload, import app adapters or source verifiers, run app-owned business suites, or add byte/hash, security, signing, provenance, integrity, trust, or restrictive admission work without exact authorization. Ordinary development, setup, hooks, push, and continuous integration must not run tests or checks automatically; current tooling compliance remains unverified until its owner reconciles those paths.

Release, security/privacy, accessibility, signing, and acceptance work applies only when the user separately authorizes its exact output, control, and scope; the presence of those SOPs does not activate them.

Purpose

This Standard Operating Procedure (SOP) governs the creation and modification of Arcane applications, components, modules, entities, styles, assets, models, adapters, and other runtime capabilities.

Arcane applications must be thin compositions of shared SDK capabilities. Arcane OS itself is an SDK-consuming application layer: its orchestrator, launcher, shell, and system artificial-intelligence app follow the same source-development, SDK-consumption, packaging, capability, and distribution paths as ordinary portable applications. Reusable portable behavior belongs canonically in the Arcane SDK. Any arcane/** tree retained in Arcane OS is a generated SDK projection, not an independently edited source authority. An application under apps/<id>/ should contain only its business-specific policy, language, data definitions, routes, and orchestration.

This is a required design and review process, not an optional refactoring exercise after an app is complete.

Core rule

Before creating any file or copying an existing implementation, write down answers to these questions in order:

  1. I need to make a _____. Describe the user-facing capability or domain behavior, not the proposed filename or technology.
  2. Could this be useful to another application? Consider current and plausible future Arcane applications, not only the app being changed today.
  3. Does it contain business logic specific to this application? Identify app-specific terminology, rules, permissions, prompts, schemas, routes, persistence choices, and workflows.
  4. Can that business logic be extracted from the core behavior? Prefer configuration, adapters, callbacks, events, slots, or injected providers so the core remains reusable.

If the core behavior can be useful elsewhere, it must be created in or moved to the canonical Arcane SDK. Arcane OS and applications may configure and orchestrate it; neither may own a private copy.

Apply this ownership decision in order:

  1. Reusable by a portable application -> Arcane SDK. Shared modules, entities, components, browser runtimes and providers, protocol/state/lifecycle machinery, themes, portable assets, and public native-capability contracts or adapters belong in the SDK.
  2. Host privilege, launcher, session, or shell responsibility -> Arcane OS. Privileged Core implementations and OS/shell composition stay in Arcane OS/Core. Applications declare and select capabilities and return an honest unsupported result when the required host is absent without disabling unrelated behavior.
  3. One-product behavior -> the owning application. Branding, prompts, data, tools, business policy, model authorities, and product orchestration remain with that application.

Never solve reuse with copied app-local or OS-local code. Arcane OS must not become the canonical source or an undeclared runtime dependency for a portable mechanism. Arcane OS reference tables remain authoritative for the host surface and implementation availability they project, but they do not originate a competing portable contract; the SDK is canonical for portable public contracts and adapters.

Procedure

1. Define the capability

Complete this statement in plain language:

I need to make a capability that allows a user or system to _____.

Describe inputs, outputs, state changes, failure states, permissions, and user-visible behavior. Do not begin with “I need a component named…” because that assumes the solution before the boundary is understood.

2. Search before creating

Inspect the canonical Arcane SDK source, its installed or materialized consumer projection, and examples before adding a new implementation. The paths below describe the projection visible to a consumer; change their canonical source in the SDK rather than hand-editing projected Arcane OS content:

  • arcane/components/ for reusable visual and interactive behavior.
  • arcane/modules/ for reusable state, integration, storage, processing, and service behavior.
  • arcane/entities/ for reusable domain-neutral records, validation, and value behavior.
  • arcane/css/ for shared tokens, layouts, and interface primitives.
  • arcane/img/ and arcane/models/ for shared assets and model definitions.
  • example/ for documented usage and extension patterns.
  • apps/ for existing app orchestration that may reveal a capability ready to be extracted.

Prefer extending a compatible shared contract over creating a near-duplicate. Do not change a shared contract in a way that silently breaks its existing consumers.

3. Apply the reuse test

Treat a capability as reusable when its purpose can be described without the name of one app, customer, case type, program, or business workflow.

Examples of reusable behavior include:

  • displaying, editing, selecting, uploading, previewing, or organizing data;
  • opening and closing dialogs;
  • storing preferences or files;
  • validating common value shapes;
  • invoking mail, artificial-intelligence, speech, or storage providers through neutral interfaces;
  • reporting progress, errors, status, or results;
  • importing HTML and coordinating component readiness.

The fact that only one app needs the capability today is not sufficient reason to keep a generally useful implementation app-local.

4. Identify app-specific business logic

Mark each requirement that depends on the app. Common business-specific concerns are:

  • product names, domain terminology, instructions, and prompts;
  • workflow ordering and decisions unique to the app;
  • domain schemas, scoring rules, legal or clinical meaning, and record relationships;
  • app permissions, publication policy, and capability requests;
  • app routes and navigation;
  • which provider, repository, or persistence policy the app selects;
  • transformations between the app's domain records and a neutral shared contract;
  • app-specific success, escalation, and failure actions.

Business logic belongs in apps/<id>/. Visual mechanics, generic state transitions, provider-neutral integrations, and domain-neutral validation do not become app-specific merely because an app uses them.

5. Extract the reusable core

Separate mechanism from policy using one or more of these boundaries:

  • Configuration: labels, options, schemas, limits, feature flags, and initial state supplied through configure(...), properties, or data attributes.
  • Events: shared components emit domain-neutral CustomEvent messages; the parent app decides what the event means and what happens next.
  • Callbacks or adapters: the app supplies conversion, persistence, authorization, or provider operations to a shared capability.
  • Slots or child content: the app supplies business-specific content without forking the shared visual shell.
  • Injected providers: shared modules depend on a narrow interface rather than app credentials, endpoints, or global business policy.
  • Record mapping: app code converts domain records into shared entity or component input shapes and converts results back when necessary.

A shared implementation must have useful neutral defaults, validate its public inputs, expose predictable outputs, and avoid importing from apps/.

6. Place each responsibility

Responsibility Location Boundary
Reusable user interface or interaction Arcane SDK (arcane/components/ projection) Parent-controlled data, labels, actions, and persistence
Reusable state, service, integration, or processing behavior Arcane SDK (arcane/modules/ projection) Provider-neutral interface with explicit errors and outputs
Reusable record, value object, or validation behavior Arcane SDK (arcane/entities/ projection) Domain-neutral data contract and invariants
Shared tokens, layouts, and interface primitives Arcane SDK (arcane/css/ projection) Neutral styling that apps may compose without duplicating
Shared image or model asset Arcane SDK (arcane/img/ or arcane/models/ projection) No app-specific branding or private content unless intentionally platform-wide
App schema, prompt, route, policy, wording, or orchestration apps/<id>/ May depend on arcane/; must not redefine it
Launcher, session, shell, or privileged host implementation Arcane OS or Arcane OS/Core OS-owned composition or host privilege; not a portable mechanism
Public native-capability contract or portable adapter Arcane SDK Capability contract; consumers report unsupported when the host is absent
Reusable usage demonstration example/<type>_<name>/ Minimal, synthetic, and independent of an app's private data
Cross-app behavioral contract test test/ Covers the shared contract and reuse boundary
App-specific business behavior test apps/<id>/test/ or the established app suite Covers domain policy and orchestration

Dependencies flow from applications and the Arcane OS shell to the SDK. SDK code must never import app or Arcane OS source or assume that either is present. Arcane OS/Core implements privileged host contracts without becoming the portable contract authority. Distribution consumes the selected materialized SDK runtime; development uses the explicit SDK source path. Do not edit the generated arcane/** projection independently.

System appearance follows the same dependency rule. Applications consume the shared theme manager and named design tokens. User-created skins are validated data, not arbitrary CSS, so they remain portable and cannot introduce selectors or network resources into another app.

7. Start every user interface with the Arcane theme

Every app and shared visual component must use the Arcane theme as its base. This preserves the user's selected appearance across Arcane OS while still allowing each app and component to develop an appropriate visual identity.

Use this cascade order:

  1. Optional shared layout: include arcane/css/layout.css first when the shared application layout is appropriate.
  2. Arcane theme: every app must load arcane/css/theme.css, which supplies the canonical light/dark variables and user-preference selectors.
  3. Arcane primitives and shared feature styles: load arcane/css/primitives.css and any other reusable Arcane styles required by the capability.
  4. App styles: load apps/<id>/...css after all shared Arcane styles.
  5. Component styles: apply component-specific CSS after the shared base within the component while continuing to consume Arcane variables.
  6. Narrow overrides: place route, state, or instance overrides last and keep their scope as narrow as possible.

The resulting order should be visible in an app document:

<link rel="stylesheet" href="./arcane/css/theme.css?v=1">
<link rel="stylesheet" href="./arcane/css/primitives.css?v=1">
<link rel="stylesheet" href="./arcane/css/<shared-feature>.css?v=1">
<link rel="stylesheet" href="./apps/<id>/<app>.css?v=1">

Paths and version values may differ, but the shared-to-specific order must not.

Apps must load arcane/modules/ThemeBootstrap.js to apply the user's shared appearance through ThemeManager. Do this early enough to avoid presenting a conflicting app-default theme before the saved preference is applied. Apps that provide a theme switcher or editor must use the shared Arcane theme components and persistence rather than establishing an app-only preference that other apps cannot respect.

Custom CSS must consume the Arcane theme variables, including shared surface, text, action, border, focus, status, spacing, and radius tokens, whenever those concepts apply. App and component styles may add new semantic variables, but their defaults should derive from Arcane variables. For example:

:root{
    --case-priority:var(--arcane-warning);
}

.case-card{
    background:var(--arcane-surface-raised);
    border:1px solid var(--arcane-border);
    border-radius:var(--arcane-radius-large);
    color:var(--text-color);
}

Write new color values with rgb(...) or rgba(...) rather than hexadecimal notation. RGB and RGBA keep channel values explicit and make color and opacity transitions easier to animate. Existing hexadecimal values may be migrated when their surrounding code is changed; do not perform unrelated palette rewrites solely for notation.

Overrides are allowed and expected when they serve an app or component. They must be layered on top of the Arcane base, remain compatible with light, dark, system, and custom user themes, and preserve accessible contrast and focus visibility. Do not replace the Arcane theme with a fixed app palette or use hard-coded colors for concepts already represented by theme tokens.

8. Define the contract before implementation

For every new shared capability, document:

  • its purpose and non-goals;
  • accepted inputs, configuration, and defaults;
  • public methods or exported functions;
  • emitted events, returned values, and error behavior;
  • required providers or browser capabilities;
  • accessibility and keyboard behavior for user interfaces;
  • credential protection, explicit privacy choices, and persistence boundaries;
  • compatibility expectations for existing consumers.

Use arcane/modules/ComponentContracts.js when multiple components or consumers need the same validated option shape or a testable domain-neutral transformation.

Shared components should allow the parent to supply domain data and decisions. A component must not silently select business policy, persist to an app-specific location, or call an app route unless that behavior is explicitly injected.

9. Implement the smallest complete split

A normal implementation consists of:

  1. the reusable mechanism in the canonical Arcane SDK;
  2. its explicit development-source mapping and pinned or materialized distribution projection;
  3. any privileged host implementation in Arcane OS/Core;
  4. the app-specific adapter or orchestration in the owning application;
  5. focused tests for the affected sides of the boundary;
  6. a synthetic example and usage notes when a new public shared contract is introduced;
  7. updated package allowlists, cache references, or machine capabilities when required.

Do not build the full feature app-local with a promise to extract it later. Establish the boundary as part of the first implementation.

10. Complete the work-amplification review

Before implementation, draw the work graph for any setup, build, package, test, model, app, or runtime path the change creates or materially alters:

  1. State the cardinality and loop multiplier across platforms, architectures, applications, models, assets, targets, test cases, retries, and processes.
  2. Inventory expensive downloads, extraction, compilation, linking, package generation, model acquisition, service initialization, and tests. Estimate representative invocation count, allocation behavior, and elapsed time without byte accounting.
  3. Classify each operation as invariant, reusable, batchable, or necessarily per item. Hoist invariant work, reuse only while real semantic inputs and the invalidation rule remain unchanged, and batch compatible work.
  4. Measure a representative cold path and compare its operation count and elapsed time with the design estimate.
  5. Eliminate redundant work before adding progress UI. Necessary long work reports phase, current item, completed/total item count, elapsed time, heartbeat, and an honest ETA when available.

Arcane OS-owned artifacts and runtime preparation must not repeat once per application. Optional hashing, signing, integrity, provenance, trust, hardening, and restrictive admission are not work-amplification techniques and remain inactive without exact authorization. An application release owns its app-specific output; Arcane OS consumes that output through the functional application contract and does not compile or test the application during OS setup.

Any intentional repetition documents the changing semantic input, why batching or reuse is unavailable, the multiplier, and the measured cost. Convenience or loop-local placement is not a justification.

11. Preserve foreground responsiveness

The responsiveness invariant applies to every user interface and command-line interface (CLI), including setup, startup, builds, model pulls, app installation, and runtime initialization:

  1. Acknowledge immediately. Create or activate the UI, or print a CLI start/status record, before the first potentially blocking operation. Show the phase and a durable error/log destination when available. A splash or status surface must exist before a required serialized boundary begins.
  2. Keep waits off the foreground. Network, disk, compilation, process, and model work must not block UI creation, event dispatch, painting, input, or the foreground thread. Use event-driven background workers for CPU-bound or blocking APIs and genuine asynchronous I/O where the platform provides it.
  3. Do not disguise blocking code. async/await is allowed for genuinely asynchronous operations, but declaring a function async, returning a promise/task, or using await does not make synchronous filesystem, compiler, child-process, or network work nonblocking. The blocking call itself must leave the foreground execution path.
  4. Bound concurrency and apply backpressure. Set explicit worker, process, network, memory, and queue limits appropriate to the resource. Do not use unbounded fan-out, unbounded Promise.all, or uncontrolled process spawning. Producers must pause or queue when consumers reach capacity.
  5. Publish live progress. Emit event-driven phase, current item, completed/total item count, and elapsed updates. Emit a heartbeat while a necessary operation cannot report granular progress so a user can distinguish work from a hang. Coalesce updates when needed.
  6. Support control. Provide cancellation and safe retry or resume when the underlying operation supports it. Define partial-output handling and keep unavoidable external-protocol or shared-state transactions narrow.
  7. Own every task. Every background operation must be awaited, joined, registered with a supervisor, or otherwise have an explicit lifecycle owner. Surface failures through the visible operation state, durable log, and CLI exit status. Unobserved fire-and-forget work is prohibited.
  8. Serialize only proven boundaries. Serialize only when an atomic transaction, shared mutable state, or unavoidable external protocol requires it. Document that boundary and its duration. Do not serialize an entire workflow for convenience, and never begin serialization before visible status exists.

Focused test source should cover acknowledgement before blocking work, foreground events during a representative slow operation, bounded concurrency, progress or heartbeat, cancellation, and surfaced worker failure. Do not execute that source unless verification is authorized.

12. Name every function and callback

Every function must have a meaningful name, including callbacks passed to event listeners, timers, promises, array methods, task runners, provider calls, and other functions. The name should describe the callback's role or terminal condition so stack traces, diagnostics, and natural-language debugging identify the actual operation instead of reporting only <anonymous>.

Do not use an anonymous arrow or anonymous function merely because the callback is short. A concise named function expression is acceptable when a separate declaration would obscure a useful local closure.

The road to callback hell is paved by missing the exit to callback heaven: name the callback.

Cross-application AI, corpus, cancellation, and terminal-workflow contracts

The following contracts apply to every Arcane application that uses the same class of capability. Historical app implementations are evidence for improving the shared contract, not sources of app-specific exceptions.

Keep this SOP synchronized with the authoritative public shapes in arcane-ai-contracts.md, the native methods in arcane-api.md, the package boundary in app-packaging.md, the test ownership rules in os-testing.md, and the conditional signing and promotion rules in build-release.md. Diagnose failures through debugging.md; do not turn a diagnosis into a speculative contract change.

Shared AI is the provider-neutral data-access and normalization boundary

The Arcane SDK module materialized at arcane/modules/AI.js is the shared artificial-intelligence data-access object (DAO) and normalization boundary for application inference. An app owns domain messages, tool meaning, its semantic result schema, presentation, and orchestration. The SDK-owned shared AI module owns provider selection, provider request construction, message normalization, structured-output translation, provider response normalization, and stable error/cancellation behavior. The Arcane bridge, Core, and native provider own host availability, transport execution, and termination of privileged native upstream work. Restrictive capability or model admission is not inferred from that ownership and requires exact authorization.

Use the object-form request APIs for all new application code:

const response=await ai.fetchRequest({
    messages,
    structuredOutput:SEARCH_RESULT_SCHEMA,
    parallelToolCalls:false,
    signal
});

Use streamRequest({...}) for streaming work and pass the same owned AbortSignal. Positional fetch(...) and streamMessage(...) signatures are compatibility internals; do not add new app consumers of them.

Application code must not:

  • call an OpenAI HTTP endpoint, Arcane.ollama.chat(...), or another provider inference endpoint directly;
  • construct provider fields such as model, stream, format, response_format, think, reasoning_effort, options, provider tool-call envelopes, authorization headers, or provider-specific response paths;
  • normalize Ollama and OpenAI results independently or branch on provider wire shapes;
  • copy shared AI request construction into an app-local helper;
  • suppress or discard complete messages, prompts, tools, schemas, documents, or provider responses merely because a diagnostic boundary exists. Diagnostics must still protect credentials, protected operational data, and content covered by an explicit privacy choice.

Direct Ollama inventory and management methods remain platform, Settings, Shell, or Terminal diagnostic/administrative surfaces governed by their documented capabilities. They are not an alternate inference DAO for an application.

The shared AI boundary must:

  • validate the declared public request shape and report malformed input before provider dispatch;
  • translate one app-supplied JSON Schema to the selected provider's native structured-output field;
  • strip persistence-only and renderer-only message metadata before provider dispatch;
  • normalize tool calls, text, usage, model identity, errors, and cancellation into the documented shared result;
  • invoke application callbacks only while the request remains current and attached;
  • preserve a stable provider-neutral error code and AbortError identity;
  • keep provider additions inside the shared adapter so app callers do not change when a provider changes.

Focused test source uses provider doubles at the shared boundary and covers the provider translation, normalized result, malformed-input handling, metadata translation, and identical application-facing behavior for supported providers. App test source asserts that the app supplies only domain messages, schema, tools, policy, callbacks, and an AbortSignal. Do not execute tests or source-contract checks unless verification is authorized.

Speech-first interaction is an application recommendation

Speech-first interaction can improve hands-free use, accessibility, review, and attention-sensitive workflows, but it is not an Arcane OS product rule. Each application decides whether spoken output or voice input fits its users and domain. The app owns narration timing, consent, labels, interruption behavior, privacy wording, and the equivalent visual or text workflow.

The Arcane SDK owns the app-neutral Arcane.speech.status(), Arcane.speech.synthesize(...), and Arcane.speech.transcribe(...) public contracts and portable adapters. SDK runtime modules own bounded playback, sequencing, supersession, object-URL cleanup, and reusable transcription interaction. Arcane OS/Core owns only the privileged host implementation and host execution. An application must use those SDK contracts, declare the capability it selects, and report speech as unavailable when the host is absent without disabling the equivalent text workflow. It must not connect directly to a speech provider or copy the mechanics into app-local or OS-local code.

A speech-first design must remain usable when speech is unavailable, denied, muted, interrupted, or only partly ready. Keep the full visual text available, provide an immediate stop/mute control, never start microphone capture without the applicable user action and capability, and expose synthesis and transcription readiness independently. Spoken output is presentation, not authorization, acknowledgement, or proof that a person heard or accepted it.

Focused test source covers unavailable and partially available roles, stop/supersede behavior, cancellation on page detach, visual-text parity, microphone denial, and the absence of direct app-to-provider speech calls. Do not execute it unless verification is authorized.

Structured output, exact enums, and model-owned defaults

When application logic consumes machine-readable output, structuredOutput must be a concrete closed JSON Schema object, not merely a prose instruction or loose JSON mode. Define the schema once in an importable app-domain module and use that same definition for shared-AI translation and runtime validation.

A result schema must:

  • declare the top-level type and every nested type;
  • use additionalProperties:false at every object level that the app interprets;
  • list every required property explicitly;
  • bound arrays, strings, numbers, and integers where the domain has a real bound;
  • reject unknown, duplicate, missing, or out-of-domain identifiers after parsing;
  • preserve one canonical field name and type across providers;
  • describe every enum value exactly, including when each value is valid and what it means.

For example, an enum description must say “Use exactly user_commitment when the user explicitly committed to act; use exactly optional_homework only when the user explicitly agreed to carry optional homework forward.” A description such as “type of follow-up” is not an adequate contract. Keep the runtime parser consistent with the declared semantic schema. This is public-contract handling, not restrictive security admission.

The system prompt describes the task, evidence rules, and decision semantics. It must not contain a second hand-written copy of the response JSON shape that can drift from the schema. Do not ask the model to infer a schema version, tolerate extra fields, or repair its own invalid output silently.

App-owned Modelfiles own normal generation defaults such as context window, temperature, prediction behavior, and other model behavior. The shared AI/provider layer owns provider defaults when no Modelfile applies. An app must not estimate token or serialized-content size or override model defaults merely to make a request appear tuned.

An app-side generation option is appropriate only when the product's semantic contract genuinely requires that provider behavior. An unavoidable external protocol or platform limit stays at its owning adapter, is surfaced honestly, and must not become an app-wide content-size, byte, or truncation rule. Heuristic byte targets, guessed token ratios, and folklore num_ctx overrides are prohibited.

Focused test source covers schema closure, required fields, exact enum semantics, real domain bounds, unknown/duplicate IDs, invalid provider output, no duplicated prompt schema, Modelfile-owned defaults, and absence of app-side byte heuristics. Do not execute it unless verification is authorized.

DBOPFS-defined complete corpora and stable independent batches

For an Arcane application corpus stored in DBOPFS, the allowed DBOPFS file keys present for the operation define the corpus. A manifest may supply titles, source labels, app-owned metadata, or packaging information, but it does not make an absent body searchable and it does not exclude an allowed DBOPFS record merely because metadata is missing. Do not refetch bundled document bodies after DBOPFS hydration.

Use this operation contract:

  1. Enumerate the allowed DBOPFS keys once for the operation and sort them by the documented stable key order.
  2. Resolve metadata without changing membership, then read each available document body in full. An unreadable or concurrently removed file becomes a bounded warning associated with that file; it does not cause a bundled-body fetch or hidden substitution.
  3. Form stable fixed-count groups from the readable ordered documents. The count is an app-domain constant. Do not change group membership based on serialized bytes, guessed tokens, provider speed, or document length, and do not truncate a document to make it fit a heuristic target.
  4. Launch each group as an independently owned asynchronous request without awaiting the preceding group. When corpus cardinality is not already bounded, use a shared bounded scheduler with explicit backpressure; do not restore serial dependency or unbounded fan-out.
  5. Await all launched requests with Promise.allSettled semantics. Retain every successful result, convert each non-cancellation failure to one structured warning, and merge successful results deterministically using score plus original corpus order for ties.
  6. Return explicit coverage containing the actual corpus count, readable/evaluated IDs, relevant IDs, failed group indexes/IDs, and whether coverage is complete. Partial success is a valid result, not a disguised full success and not an all-or-nothing failure.

A representative orchestration shape is:

const corpus=await loadCompleteCorpusFromDBOPFS();
const groups=stableFixedCountGroups(corpus.documents,FILES_PER_GROUP);
const outcomes=await Promise.allSettled(
    groups.map(function launchIndependentGroup(group,index){
        return requestGroup({group,index,signal});
    })
);
const result=mergeSettledCorpusResults({corpus,groups,outcomes});

Progress must come from actual file counts. The initial total is the number of enumerated DBOPFS files in scope. Completed work is the number of unreadable/skipped files whose load has settled plus each settled readable group's real length. Unless cancellation stops the operation, the final completed count must equal the enumerated total. Do not derive user-visible progress from a manifest count, configured maximum, guessed batch size, response order, or byte estimate. A progress callback is observational: an exception in it must not change the search result.

Corpus and group warnings stay outside model prompts. Show them in the local UI and, when needed, a privacy-safe console diagnostic. Within the corpus/tool-result payload, keep the verbatim user request and successful grounded records available alongside otherwise authorized prompt context, but do not inject “the search was incomplete” or raw failure text. Warning text can change inference and cause the model to answer the diagnostic instead of the user.

Cancellation is not partial success. If the page-owned signal aborts, stop launching queued work, terminate active requests, suppress later progress, and return the normalized cancellation outcome rather than warnings for every cancelled group.

Focused test source covers DBOPFS key authority, metadata-only manifests, no body refetch, complete document content, stable fixed-count groups including a very long document, independent launch, bounded scheduling where applicable, all-settled partial success, deterministic merge order, actual-file progress, warning/prompt separation, and cancellation without later progress. Do not execute it unless verification is authorized.

Verbatim user intent and privacy-safe diagnostics

Capture the latest real user-role message from the request record before tool execution and propagate that exact string to retrieval. Validate emptiness with a trimmed view if needed, but return and send the original text unchanged, including punctuation, whitespace, line breaks, names, and qualifiers.

The model may decide whether a retrieval tool is appropriate, but it must not author, summarize, “improve,” normalize, or replace the retrieval query. Tool schemas therefore must not request a rewritten query, user_goal, known_context, or similar model-generated substitute when the original user message is available. Synthetic timebox, retry, closeout, and continuation instructions are internal control messages and must never become the user's search text.

Focused test source uses a request with leading/trailing whitespace, embedded newlines, punctuation, and meaningful qualifiers; it covers complete propagation and proves that conflicting model tool arguments cannot replace it. Do not execute it unless verification is authorized.

Diagnostics are complete enough to diagnose the selected boundary and must not truncate, clip, tail, summarize away, or silently omit ordinary prompts, messages, tools, schemas, request bodies, document content, model responses, or errors. Preserve correlation, operation, item/group identity, timing, status, and stable error details when they help establish the first divergence.

Protect credentials, secrets, private keys, protected operational data, and content covered by an explicit privacy choice. Keep those protected values out of durable logs and external output. Do not generalize that narrow protection into blanket suppression of complete diagnostic content. Expected cancellation remains ordinary control flow, diagnostic failure must not alter the user operation, and a persistent telemetry or storage design remains an app-owned product decision.

Structural tool-call messages and contained tool interfaces

Every Arcane structural tool-call argument object must include message as a nonempty user-facing string that states the immediate next prompt or operation status. The ordinary transcript presents the call's message; complete raw arguments or envelopes may appear only in an explicitly user-selected tool-inspection surface or developer-console diagnostic, never as the default conversational response.

Every structural call must receive a matching executed, declined, cancelled, or not-executed tool-result turn before another user turn; displaying a call alone never settles it.

Internal tool parsing, dispatch, protocol, and settlement failures belong in complete developer-console diagnostics and must not be appended as transcript messages. A semantic tool interface, including every nested tool container, must remain inside its owning card and viewport under narrow widths, content growth, and text zoom. Preserve the complete content by wrapping it; when the content cannot wrap coherently, use a local content scroller inside the owning container. Never clip, truncate, elide, or allow tool content to escape its owning interface.

Page-owned cancellation must terminate the actual upstream operation

Every page or similarly detachable application surface owns one parent AbortController for its asynchronous lifetime. Register a one-shot pagehide or equivalent detach handler before launching page-owned work. That handler aborts the parent controller, clears page timers, disposes subscriptions/timeboxes, and prevents new work from being queued. An independently cancellable operation may own a child controller linked to the parent detach signal; cancelling that child must not cancel unrelated page work, while detaching the page must still abort every linked child.

The same signal must propagate through the whole path:

page/app adapter -> shared AI DAO -> Arcane frontend bridge -> Core request owner -> native/provider adapter -> actual network socket, response stream, inference job, process, or worker

Local promise rejection is not cancellation if upstream inference continues. Each provider adapter must retain the handle that can stop its real operation and invoke it on abort—for example AbortController.abort(), request/response destruction, socket close, native job cancellation, or child-process-tree termination. If a provider cannot cancel safely, document that limitation, prevent all downstream effects, and do not claim upstream cancellation.

The frontend bridge uses exact control messages for one request and for every request owned by a detached page. A pre-aborted request sends no normal request frame. Pending entries own their abort listener and timeout, remove both on every terminal path, notify Core without awaiting a slow transport acknowledgement, reject locally with a stable AbortError, and ignore late replies. Core owns one controller per active request, validates request IDs and exact control-frame keys, aborts all active controllers when its input/session closes, and never emits success after abort.

Every queued, retry, and continuation boundary must check the signal:

  • before enqueueing and before provider dispatch;
  • after model/resource availability resolution and every awaited dependency;
  • before a retry, timer callback, automatic greeting, tool continuation, or follow-up request;
  • before progress, persistence, speech, navigation, or UI mutation;
  • after the provider returns but before invoking the app callback.

Normalize page-owned cancellation to name:'AbortError' plus the documented shared code. Treat it as expected control flow: clear placeholders and ownership, but do not show a service-failure message, create partial-success warnings, retry, or persist an assistant response.

Native hosts must cancel all page-owned Core requests on top-level reload/navigation, renderer or web-process termination, host close, and Core disposal. Cancelling only an app promise while leaving the bridge, Core queue, or model generation alive means the changed interaction is incomplete.

Focused test source covers pre-abort, in-flight abort, exact per-request cancellation, page-wide cancellation, listener/timer cleanup, slow transport acknowledgement, ignored late response, cancellation during availability resolution, destruction/cancellation of the actual upstream handle, host navigation/termination, no retry/continuation after detach, no late progress or persistence, and provider parity. Do not execute it unless verification is authorized.

Terminal conversation closeout tools

A terminal closeout is a provider-neutral tool contract, not an app-specific prose convention. Put generic tool construction, semantic normalization, and sole-call classification in a canonical Arcane SDK module, materialized for consumers at a path such as arcane/modules/ConversationClosingReport.js. The app adapter supplies only its tool name, domain wording, semantic trigger policy, optional consent/persistence adapter, presentation preference, and terminal UI transition.

The closeout tool is offered on every eligible conversational request until completion is successfully committed. Do not remove it because a user disabled a decorative closeout preference or remembered-action preference; those preferences control presentation and optional persistence, not whether the model can report a semantic ending. After completion, remove the tool because the conversation accepts no further request.

Trigger on semantic user-ending intent: the user expresses that they are ending, finished, wrapping up, leaving, or selects the app's explicit Complete action. Do not use an exact phrase, a keyword proxy such as “recap,” response length, elapsed time, or a vague “clearly” test. Do not close while requested work remains open or after a routine answer. A manual Complete action may add an internal instruction for the current inference, but must not rewrite or persist it as user-authored text.

The model emits exactly one complete final_message plus optional remembered_actions. This illustrative schema is derived from the shared constructor; use its exported constants rather than copying the literal bounds into application code:

const TERMINAL_CLOSEOUT_SCHEMA={
    type:'object',
    additionalProperties:false,
    properties:{
        final_message:{type:'string',minLength:1},
        remembered_actions:{
            type:'array',
            items:{
                type:'object',
                additionalProperties:false,
                properties:{
                    text:{type:'string',minLength:1},
                    basis:{
                        type:'string',
                        enum:['user_commitment','optional_homework'],
                        description:'Use exactly user_commitment for an explicit user commitment. Use exactly optional_homework only for optional homework the user explicitly agreed to carry forward.'
                    }
                },
                required:['text','basis']
            }
        }
    },
    required:['final_message']
};

Do not split the final response into rigid model fields such as outcome, progress, next steps, and warm closing. Those optional rhetorical elements belong inside the one model-authored final_message; a multi-field template creates brittle assembly, duplicated prose, and schema drift.

The runtime parser independently enforces the declared JSON/plain-object shape, exact keys, one complete nonblank final message, and exact remembered action fields and enum values. Return a plain normalized result. The terminal tool must be the sole tool call; report mixed, malformed, or unoffered calls without partially executing them. A manual closeout request selects that tool and disables parallel tool calls. Do not commit malformed streamed tool output to the transcript; preserve the complete diagnostic at its owning boundary.

Remembered actions are not implied by model output. Include only a commitment or optional homework the user explicitly agreed to carry into a later conversation, then request separate, fresh consent before local persistence. Report saved, failed, or declined status in the same terminal message. Declining or failing persistence must not prevent the final message from closing the conversation. The tool itself performs no action, navigation, notification, email, task creation, or external delivery.

A closeout does not require links. The absence of a URL, email address, telephone link, or source citation must never make a valid terminal closeout fail. When a source is useful, an exact document title can be sufficient. A semantic response-purpose decision may describe whether the response is a grounded answer or terminal closeout; it must not become a provenance, security, or restrictive link-admission gate without exact authorization.

Use this single terminal commit sequence:

  1. Confirm every returned tool name was offered for this exact request.
  2. Classify the sole terminal call and normalize its semantic arguments once.
  3. Ask separately for remembered-action consent and incorporate the local result into one terminal message.
  4. Record the central semantic response purpose once for the final visible message.
  5. Through one response commit coordinator, persist and render that same accepted message before marking the UI complete.
  6. Only after successful persistence/rendering, dispose timers and pending work, enter the terminal UI state, and reject every later submission.

The completed shared chat state expands and retains the transcript, hides the timer, composer, upload, speech, language, and completion controls, disables every input/send path, moves focus to the transcript without losing content, and scrolls the terminal message into view. Guard both the visible controls and the programmatic submission API; disabling a button alone is insufficient. Page-owned abort and response revision guards must prevent an older request, retry, tool continuation, automatic greeting, or speech callback from adding post-close output.

Focused test source covers always-offered-until-complete behavior, semantic triggers and false positives, manual sole-tool use, malformed/unoffered/mixed tool handling, schema and runtime normalization, exactly one complete final message, separate remembered-action consent and every save outcome, no link requirement, one semantic response-purpose decision, persistence-before-completion order, transcript expansion/control hiding/focus, disabled visible and programmatic submissions, and no late post-close work. Do not execute it unless verification is authorized.

Centralized semantic policy and one decision point

When the product's public semantic contract genuinely defines a finite choice, represent it with one plain enum record and one normalizer/decision function:

const RESPONSE_PURPOSE={
    GROUNDED:'grounded-response',
    TERMINAL_CLOSEOUT:'conversation-closeout'
};

The decision function normalizes the closed semantic enum and returns a plain result containing the purpose, outcome, and reason code. Unknown or malformed values return an explicit contract error. Downstream persistence, rendering, or delivery consumes that result instead of reinterpreting the purpose.

Do not spread the same semantic decision across flags such as isCloseout, linksRequired, or displayCloseout, and do not normalize the same tool report twice. This mechanism is semantic consistency, not security, provenance, trust, freezing, or restrictive admission.

Focused test source covers each enum member, malformed values, the complete semantic result, and downstream use of that result. Do not execute it unless verification is authorized.

Shared placement and loose coupling

Place provider translation, normalized AI requests/results, generic terminal-tool construction/normalization, semantic response-purpose mechanics, abort/error normalization, bounded schedulers, and shared terminal chat state in the canonical Arcane SDK. A consumer may materialize that content under arcane/, but that projection is not edited source. Keep app-specific prompts, schemas, corpus metadata rules, result ranking meaning, tool names, consent wording, persistence adapters, model authorities, and UI orchestration in the owning application. Keep only shell-specific system-AI policy and privileged host implementations in Arcane OS.

Shared modules accept narrow records, callbacks, policy enums, and AbortSignal; they do not read app globals or import app files. App adapters compose shared exports; they do not copy their bodies or expose provider wire details. When two apps need a variation, extend one neutral shared contract and update affected consumers. Run consumer verification only when authorized.

Focused contract test source belongs with the shared mechanism under test/; app business-policy and orchestration test source stays in the app-owned suite. When verification is authorized, exercise runtime behavior at the cheapest real boundary that answers the question.

Vanilla-test 2.1.0 convention

Every repository JavaScript test case uses the shared vanilla-test 2.1.0 adapter at test/support/vanilla-test.mjs, reached through the correct repository-relative import. Use node:assert/strict for equality, throws, and rejection semantics. Do not import node:test directly from an app or test file and do not instantiate VanillaTest outside the shared lifecycle support.

The shared adapter owns exactly one vanilla lifecycle per Node-orchestrated case and settles it once. Node remains the only orchestrator for discovery, suites, hooks, nested tests, filtering, isolation, timeouts, cleanup, concurrency, reporting, and exit status. Preserve the original failure and stack and consume the vanilla report without printing a second ANSI report. A callback-style case has arity exactly two and must not also return a Promise. No library or case calls process.exit().

When adding tests for the contracts above:

  • import test, describe, it, and hooks from the shared adapter;
  • name every case body and callback;
  • prefer strict behavioral assertions and provider/transport doubles with observable call counts;
  • prove success, malformed input, boundary rejection, cancellation, partial success, and late-callback suppression;
  • keep synthetic content free of credentials and protected user data;
  • let the runner own cleanup, timeout, and exit behavior.

Conditional source, package, native-build, signing, and push boundaries

These are conditional artifact boundaries, not one mandatory chain for every source edit. Select only the boundary the user requested. Do not restore the obsolete practice of regenerating or verifying every app package on every push.

Boundary Select it when Required work It does not select
Source Every implementation or documentation change Review the intended source and diff; update focused test source when useful Test/check execution, current dist, a native executable, or release readiness
Cache reference A served/imported source reference changes Update every affected ?v= or equivalent reference and its consumer contract An app semantic version change or automatic browser verification
Selected dist A demo, package investigation, or app release requires a packaged browser output Package only <app-id> and review selected source/generated changes; run package checks only when authorized or required by that output All-app regeneration, hashes/receipts, or an OS release
App release The app is explicitly being released Run npm run app:release -- <app-id> for that selected app; run its suite only when authorized or required by the release output Another app's behavior or Arcane OS release acceptance
Native rebuild A native artifact is explicitly requested Build only the selected app/target and launch that new output when requested Other targets, automatic checks, signing, or a full machine distribution
Signing The user expressly authorizes the exact selected artifact, mode, and scope Keep unsigned-local-test, development-signed, and production-signed commands separate and perform only the authorized mode General security, trust, provenance, or release approval
Push Remote repository delivery is selected Recheck main, coordinate overlapping dirty files, stage/commit only intended paths, and push without force Authority to include unrelated work, rewrite history, or bypass branch/reviewer policy

For rapid development, the normal path is source -> reviewed diff. Tests and npm run check run only when explicitly requested. Package, native, signing, and release work remains unselected unless the request names that output.

For a current browser demo, use source -> affected cache references -> selected app package -> serve. Run npm run demo:check -- <app-id> or inspect the live browser only when verification is explicitly authorized or required by the selected output.

For a requested native executable, use source -> affected cache references -> selected app package -> selected native rebuild -> launch when requested. Signing and runtime verification are separate exact selections. Package and rebuild the current selected source before launch; report every test or check not run.

Before any selected commit in a shared dirty checkout, re-read git status, confirm the active branch is main, identify the owner of every unrelated change, and stage exact intended pathspecs only. Do not pull, rebase, stash, reset, clean, package shared payloads, or otherwise mutate another owner's active work merely to make delivery convenient. A successful push command is sufficient delivery evidence unless the user explicitly selects a different remote-evidence boundary.

Focused test source and review may cover cache-reference coverage, package/source consistency when selected, malformed or hand-edited generated manifest handling, current-output launch rather than stale-output fallback, and signing-mode separation when signing is expressly authorized. Do not execute tests or checks unless authorized, and do not run an all-app, all-platform, or production matrix merely for a development handoff.

Corrected anti-patterns

Reject these patterns during design and review:

Anti-pattern Required correction
An app calls a provider or builds {model, messages, format, think, options} inline Call the shared object-form AI DAO with domain messages, one schema, tools/policy, callbacks, and AbortSignal
A prompt says “return JSON” or duplicates a hand-written result example Supply one closed JSON Schema and keep the prompt about task semantics
An enum lists values without exact meaning Describe when to use every exact value and enforce the same semantics at runtime
An app sends folklore num_ctx, temperature, prediction limits, guessed token counts, or serialized-content targets by default Let the Modelfile/shared provider own defaults; keep unavoidable provider/platform limits local to their adapter
A model rewrites the user's retrieval query Snapshot and propagate the latest real user message verbatim
A manifest or bundled fetch silently defines a DBOPFS corpus Enumerate DBOPFS keys; use the manifest only for metadata and read full stored bodies
Variable byte-packed/truncated or serial document requests Use stable fixed-count full-document groups with independent asynchronous settlement
One failed group discards every successful group Return deterministic partial success plus structured coverage/warnings
Manifest counts, byte estimates, or configured maxima drive progress Count actual enumerated and settled files
Warning/error text is appended to the next model prompt Keep warnings in UI/local diagnostics and prompts grounded only in successful records
Diagnostics omit or truncate ordinary requests, responses, prompts, schemas, tools, or documents Preserve complete diagnostic content while protecting credentials, protected operational data, and explicit privacy choices
Aborting rejects the renderer promise but leaves model generation running Propagate the signal and terminate the provider's actual upstream handle
Detach allows a timer, retry, queued batch, or tool continuation to run Check the signal at every queue/await/effect boundary and cancel page-wide work
A closeout preference removes the terminal tool Offer it until completion; use preferences only for presentation and separately consented persistence
Exact words, “recap,” response length, or “clearly” trigger closeout Evaluate semantic user-ending intent or the explicit Complete action
A closeout is assembled from many rigid model fields Require one complete final_message plus optional remembered actions
Closeout succeeds only when it contains a link Make no-link closeouts valid and record one semantic response purpose
A finite semantic decision is controlled by several booleans or normalized twice Normalize one closed semantic enum and consume one plain decision result
The UI hides one button but programmatic submissions remain possible Enter one terminal state that hides controls, disables every path, focuses the transcript, and rejects submissions
A user asks to launch without tests and the old executable is opened Repackage/rebuild current source first; leave tests unselected and report that omission
Every push regenerates all apps, runs tests, or signs every target Select only the requested artifact boundaries and keep invariant work outside app loops
A test imports node:test or creates its own vanilla lifecycle Import the shared adapter; keep Node orchestration and one vanilla lifecycle per case

Focused implementation checklist

Before implementing an affected feature, record and complete the applicable items:

  • Shared AI DAO method and object request chosen; no app-built provider payload.
  • One concrete JSON Schema and consistent runtime parser defined.
  • Every enum value has exact semantics; prompts do not duplicate the schema.
  • Modelfile/shared defaults retained; no app-side byte, token, or content-size heuristic added.
  • Latest real user message captured and propagated verbatim.
  • DBOPFS corpus membership, stable order, full-document load, and fixed group count defined.
  • Independent settlement, partial-success coverage, deterministic merge, actual-file progress, and warning channel defined.
  • One page-owned AbortSignal reaches every layer and the actual upstream operation.
  • Queue, retry, timer, continuation, progress, persistence, and UI boundaries recheck cancellation/current revision.
  • Terminal tool always offered until completion, uses one final_message, and is the sole call.
  • Remembered actions require explicit prior agreement plus separate persistence consent.
  • No-link closeout accepted; one semantic response-purpose enum and one complete final-message commit used.
  • Successful terminal message commits before controls hide; every post-close submission path fails.
  • Reusable mechanisms live canonically in the Arcane SDK; any consumer arcane/** tree is a generated projection, and app files contain only domain policy and orchestration.
  • Tests import the shared vanilla-test 2.1.0 adapter and use strict assertions.
  • Focused behavioral and contract test source covers malformed, failure, cancellation, partial, and late-result cases without automatic execution.
  • Conditional source/cache/dist/release/native/signing/push boundaries selected and non-selected boundaries documented.
  • When commit/push is selected, intended files are coordinated in the live working tree, exact paths are committed, and the push succeeds without including unrelated work.

Rules by artifact type

Shared components, modules, entities, themes, browser runtimes, providers, portable assets, and public native-capability adapters in the sections below are Arcane SDK artifacts. Arcane OS and ordinary applications consume them through an explicit SDK development-source path or selected materialized distribution content; they do not originate or hand-edit a competing copy.

Shared components

A shared component must:

  • use domain-neutral names and default language;
  • accept parent data and configuration instead of reading app globals;
  • expose a documented readiness signal and stable methods when asynchronous HTML import is involved;
  • emit domain-neutral events with documented detail shapes;
  • let the app own persistence, routing, and business outcomes;
  • resolve its own shared dependencies from a stable component or module-relative base;
  • support keyboard use, focus behavior, accessible labels, empty states, loading states, and errors;
  • load the Arcane visual base and use shared theme variables and style primitives;
  • layer component-specific styles after the Arcane base without resetting or overriding the user's theme at document scope;
  • remain legible and operable under the supported light, dark, system, and custom Arcane themes;
  • be usable by a synthetic example that contains no app-specific data.

An app may wrap or configure a shared component. It may not copy the component merely to change labels, data sources, persistence, actions, or layout options that can reasonably be expressed through the public contract.

Shared modules

A shared module must:

  • perform one coherent, reusable responsibility;
  • accept configuration or narrow dependencies instead of app-specific imports;
  • avoid embedded credentials, private endpoints, and app-only environment assumptions;
  • validate inputs and make failure behavior observable;
  • keep long operations off the foreground execution path and expose an owned asynchronous lifecycle with progress and cancellation where safe;
  • avoid uncontrolled global side effects;
  • export testable behavior when browser-independent logic exists;
  • document whether operations are synchronous, asynchronous, persistent, destructive, or networked.

Shared entities

A shared entity must:

  • represent a reusable record or value concept rather than an app workflow;
  • define defaults, normalization, serialization, and validation deliberately;
  • keep app-specific scoring, labels, permissions, and workflow transitions outside the entity;
  • remain usable without loading a particular app;
  • preserve backward compatibility or include an explicit migration when its stored shape changes.

If an entity name only makes sense inside one application's business domain, it normally belongs in that app. Extract reusable value objects or validators from it when possible.

Applications

An application must:

  • compose pinned or explicitly source-mapped Arcane SDK capabilities rather than duplicate them;
  • load Arcane base styles before all app-specific styles;
  • load and apply the user's shared Arcane theme instead of imposing an app-only default palette;
  • build app-level visual customization and overrides from Arcane theme variables;
  • keep only app-specific policy, content, routes, schemas, and orchestration locally;
  • map app records into neutral shared contracts at the app boundary;
  • request only the machine capabilities it needs;
  • return an honest unsupported result when a selected host capability is absent instead of depending on undeclared Arcane OS source;
  • declare the complete selected distributable content in arcane-package.json without byte/hash or restrictive admission gates;
  • keep private source material, credentials, and development-only files outside public packages;
  • explain why every app-local component, module, or entity is business-specific;
  • publish app-owned compiled output through the application's release process rather than making Arcane OS setup compile it;
  • consume OS-owned runtimes and tools without repeating OS-owned preparation once per app;
  • render or acknowledge before long work and keep that work in a bounded, owned background operation.

Arcane OS is subject to this same application contract for its orchestrator, launcher, shell, and system-AI application layers. Its additional ownership is limited to launcher/session composition, privileged/native host implementations, and shell-specific policy.

Core-only application local-AI policy

Local-model aliases, definitions, prompts, and ordinary generation defaults are app-owned package policy. The portable SDK owns provider-neutral mechanics, and Arcane OS/Core owns privileged host execution plus the complete actual provider catalog. Renderer code must not duplicate either authority.

An app that supports local inference authors one localAIModelPolicy field and one alias-to-definition list in apps/<id>/arcane-package.json:

{
  "localAIModelPolicy": {
    "verified_only": false,
    "models": [
      {
        "name": "EXAMPLE:8b",
        "definition": "Example-8B.Modelfile"
      }
    ]
  }
}

Use this procedure:

  1. Put each product Modelfile directly under its owning apps/<id>/ directory, include it in that app's selected package content, and declare one canonical Ollama name plus one app-relative Modelfile basename. Do not place product definitions in another app or in the platform model directory.
  2. verified_only remains a compatibility field in the authored contract. Ordinary secure:false development uses false and does not enforce digest, provenance, integrity, trust, or restrictive model admission. A true value may activate only after the user expressly authorizes that exact control and the caller explicitly selects secure:true.
  3. Package the selected app through its app-owned output process. Preserve the complete declared Modelfiles and normalized localAIModelPolicy in the appropriate host descriptor. Reject a genuinely unreadable or malformed descriptor, but do not compare byte counts, sizes, hashes, digests, receipts, signatures, or immutable identities.
  4. Keep product model policy out of generic SDK globals. The browser package and native host consume only the records their documented functional contract owns; this is an ownership boundary, not security admission.
  5. Populate local-model controls from the complete ordered Arcane.localAI.status().models.ollama result. Do not add an app-owned byte, GPU-name, alias, family, provenance, or trust filter. Core reports the provider's actual available catalog, readiness, and honest unsupported or failure state.
  6. Without an app-scoped Core, report local AI as unavailable and keep the browser application's ordinary text/provider workflow functional. Do not probe or call Ollama directly or infer availability from a loopback port.

Focused test source covers the policy shape, exact Modelfile ownership, package-record emission, Core-only availability projection, complete catalog rendering, and browser behavior without Core. Optional secure-mode behavior is covered only when that exact control is authorized. Do not execute tests unless verification is authorized.

Decision examples

Example: business-specific editor

Need: “Allow a user to draft and save a case analysis.”

  • Reusable core: Markdown editing, preview, validation hooks, save state, and accessible controls.
  • App-specific logic: the case-analysis schema, prompt text, authorization, case identifier, storage location, and post-save workflow.
  • Placement: editor in the Arcane SDK (materialized at arcane/components/); contract normalization in the SDK (materialized at arcane/modules/) if shared; case adapter and persistence orchestration in apps/<id>/.

Example: app dashboard

Need: “Let users choose which operational panels appear.”

  • Reusable core: render available definitions, track selection state, emit changes, and display neutral empty/error states.
  • App-specific logic: available panels, their business meaning, user permissions, and where preferences are stored.
  • Placement: configuration component in the Arcane SDK (materialized at arcane/components/); definitions and persistence adapter in apps/<id>/.

Example: domain record

Need: “Represent a legal matter with parties, deadlines, and filing status.”

  • App-specific entity: the legal matter and its workflow belong in the legal app.
  • Reusable extraction: generic file descriptors, people/contact values, date validation, and persistence interfaces may belong in the Arcane SDK (materialized at arcane/entities/ or arcane/modules/) if their contracts are genuinely cross-app.

Prohibited shortcuts

Do not:

  • copy a shared component or module into an app or Arcane OS to make a small variation;
  • hand-edit an arcane/** SDK projection as though it were canonical source;
  • put app names, domain terminology, hard-coded routes, private endpoints, or credentials in shared code;
  • make shared code import from apps/;
  • load app or component CSS before the Arcane base and depend on accidental cascade behavior;
  • replace the user's Arcane theme with a fixed app palette;
  • hard-code colors where an Arcane theme token expresses the same purpose;
  • reset shared theme variables at broad scope merely to brand one component;
  • use an app global when configuration, an event, or an injected provider provides a clear boundary;
  • create a second entity for the same record shape because an app uses different labels;
  • let a shared component decide domain persistence or workflow completion;
  • expose a breaking shared contract change without updating every affected consumer and its test source;
  • publicly serve repository roots or broad source directories instead of the selected application package;
  • place invariant downloads, extraction, compilation, model acquisition, or tests inside a per-app, per-model, per-asset, or per-target loop;
  • introduce or repeat hashing, signing, integrity, provenance, trust, security, or restrictive admission without exact authorization;
  • add progress reporting as a substitute for removing provably redundant work;
  • delay UI creation or initial CLI status until after network, disk, compilation, process, or model work;
  • call synchronous blocking work from an async function on the foreground thread, use unbounded concurrency, or start unobserved fire-and-forget work;
  • serialize an entire workflow when only a narrow shared-state, transaction, or unavoidable external-protocol boundary requires ordering;
  • defer obvious reuse extraction until after release.

Verification

Tests, checks, browser/visual inspection, and validation builds are not automatic. When the user explicitly authorizes verification, select the smallest boundary that answers the question.

For a shared capability:

  • add or update focused test source under test/ for input normalization, outputs, errors, and compatibility;
  • keep shared source domain-neutral;
  • add or update a browser example when it improves the public contract; and
  • when runtime verification is authorized, exercise only the selected lifecycle, readiness, event, accessibility, route, theme, or consumer boundary.

For an app:

  • add or update test source for its adapter, mapping, policy, and orchestration independently from the shared mechanism;
  • preserve Arcane style order and shared appearance preferences; and
  • inspect themes, run npm run app:inspect -- <app>, build/dry-run a package, or run npm run app:check -- <app> only when that verification or selected output is authorized.

When the user explicitly requests the development check, the command is:

npm run check

Use npm run check:integration only for explicitly requested portable Arcane OS integration verification, and npm run release:check:arcane-os only for an explicitly selected Arcane OS release output. The selected output consumes the app-published ARCANE_APP_RELEASE.json through the functional package contract and never imports app adapters or runs app source/content/business verification. An application's complete suite runs only when authorized or required by that selected application release.

Required design record

Use this short record in an issue, pull request, implementation note, or review description:

### Arcane capability decision

- I need to make a: [user-facing capability]
- Could other applications use it: [yes/no and why]
- App-specific business logic: [policy, terms, routes, domain schemas, provider-policy constraints, or none]
- Reusable core: [mechanism and neutral contract]
- Extraction boundary: [configuration/events/adapters/slots/providers/record mapping]
- AI boundary: [shared object-form DAO method, domain input/schema, provider-neutral normalized result, or not applicable]
- Structured-output contract: [concrete JSON Schema, exact enum semantics, runtime parser, and model/default owner]
- Corpus contract: [authoritative store, stable full-document grouping, concurrency bound, partial-success coverage, actual-count progress, or not applicable]
- User-intent and diagnostic handling: [verbatim request source, complete diagnostic path, and exact credential/protected-data/privacy exclusions]
- Cancellation chain: [page-owned signal, bridge/Core/native propagation, actual upstream termination, and detached-work suppression]
- Terminal closeout: [always-offered tool, semantic trigger, final-message schema, remembered-action consent, semantic response purpose, and terminal UI]
- Central policy decision: [plain finite enum, single semantic owner, plain decision result, and rejected parallel booleans]
- Arcane theme base: [shared styles and theme loader]
- CSS layer order: [Arcane base -> shared feature -> app/component -> narrow override]
- User-theme verification: [themes and states checked]
- SDK files and consumer projection: [canonical SDK paths plus materialized `arcane/**` paths, or none]
- Arcane OS/Core files: [launcher/session/shell/privileged-host paths or none]
- App files: [apps/<id> paths or none]
- Contract and compatibility impact: [new/extended/unchanged and affected consumers]
- Verification authorized and run: [tests, example, app checks, packaging checks, or none]
- Verification not run: [all unselected tests/checks/builds]
- JavaScript test convention: [shared vanilla-test 2.1.0 adapter, Node orchestration, and node:assert/strict]
- Delivery boundaries selected: [source / cache reference / selected dist / app release / native rebuild / signing / push, with non-selected boundaries]
- Work cardinality and loop multiplier: [items x nested items]
- Expensive-operation estimate: [representative cold-path operation count, allocation behavior, and elapsed time]
- Work classification: [invariant / reusable / batchable / necessarily per item]
- Hoisting, caching, and batching: [what runs once; semantic inputs and invalidation rule]
- Justified repeated work: [item-specific reason and measured cost, or none]
- Remaining-work visibility: [phase/item/count/elapsed/heartbeat/ETA as applicable]
- Immediate acknowledgement: [UI/CLI state visible before blocking work]
- Async owner and error path: [worker/task supervisor, visible error, log, exit status]
- Concurrency and backpressure: [explicit limits and queue behavior]
- Progress and heartbeat: [events, cadence, coalescing]
- Cancellation and retry/resume: [safe boundaries and partial-output handling]
- Required serialization: [shared-state/transaction/external-protocol boundary and why]

If “SDK files and consumer projection” is none for a generally useful behavior, the record must explain why extraction is not currently safe or coherent. Convenience and schedule alone are not sufficient reasons.

Definition of done

A new capability is complete only when all applicable statements are true:

  • The four core questions have written answers.
  • Existing Arcane capabilities were checked before new code was created.
  • Reusable mechanism and app-specific business logic are separated.
  • Reusable portable source is canonical in the Arcane SDK; any retained Arcane OS arcane/** copy is a generated consumer projection.
  • Shared code is domain-neutral and has no dependency on an app.
  • Applications use the shared object-form AI DAO and contain no provider request construction or provider response normalization.
  • Structured model output has one concrete JSON Schema, exact enum semantics, a consistent runtime parser, and Modelfile/shared defaults.
  • Retrieval propagates the real user request verbatim; diagnostics preserve complete selected-boundary content while excluding credentials, protected operational data, and content covered by explicit privacy choices.
  • A DBOPFS corpus is defined by its allowed stored keys, reads complete documents, uses stable fixed-count independently settled groups, preserves partial success, reports actual-file progress, and keeps warnings out of model prompts.
  • One page-owned AbortSignal reaches the shared AI DAO, bridge, Core, native host, and provider's actual upstream operation; detach prevents queued, retried, continued, and late-effect work.
  • A terminal closeout tool remains offered until completion, uses a semantic user-ending trigger and one complete final_message, requires separate consent for remembered actions, accepts no-link closeouts, and records one semantic response-purpose result.
  • Terminal UI state is committed only after the accepted final message, expands the transcript, hides and disables controls, and rejects visible, programmatic, queued, retried, and late post-close submissions.
  • Finite policy choices use one centralized enum and decision point, without scattered booleans, bypasses, or duplicate validation.
  • Public inputs, outputs, events, errors, and defaults are documented.
  • Shared visual behavior is configurable and accessible.
  • Every app and visual component starts from the Arcane theme, applies saved user appearance preferences, and layers custom CSS afterward.
  • App and component overrides derive from Arcane tokens and remain usable across supported themes.
  • App-local files can be justified as business-specific orchestration or policy.
  • Arcane OS-local files can be justified as privileged host/Core, launcher/session/shell composition, or shell-specific policy.
  • Every new or modified function and callback is named for useful stack traces and diagnostics.
  • The work-amplification review records cardinality, loop multipliers, and a representative cold-path operation count, allocation behavior, and elapsed time before implementation.
  • Invariant expensive work runs once, batchable work is batched, reusable output has a clear semantic invalidation rule, and every necessary per-item repetition is justified and measured.
  • Redundant scans and operations are removed before progress is added, and necessary long-running work remains visibly active.
  • UI and CLI acknowledgement precedes potentially blocking work; long operations use genuine asynchronous I/O or an owned background worker and do not block UI creation or the foreground thread.
  • Concurrency is bounded with backpressure, progress or heartbeat remains live, cancellation and retry/resume are supported where safe, and every worker failure reaches an observer.
  • Serialization is limited to documented shared-state, transaction, or unavoidable external-protocol boundaries entered only after visible status exists.
  • Focused shared and app test source covers the boundary without automatic execution.
  • JavaScript tests use the repository's shared vanilla-test 2.1.0 adapter, keep Node as orchestrator, and use node:assert/strict.
  • A synthetic example documents a new shared public contract when it materially improves reuse.
  • Package allowlists, cache references, capabilities, and versioned asset references are updated when the changed boundary requires them.
  • Tests and checks run only when explicitly authorized or required by a selected output, and the handoff reports every check not run.
  • Source, cache-reference, selected-package, release, native-build, signing, and push boundaries are selected explicitly; an ordinary development edit does not regenerate or verify every app package.

Review gate

Reviewers must be able to explain every app-local component, module, and entity as business-specific policy or orchestration, and every Arcane OS-local mechanism as privileged host/Core, launcher/session/shell composition, or shell-specific policy. If an app-local or OS-local file implements a reusable form control, persistence adapter, file browser, modal, status panel, provider wrapper, record normalizer, protocol/state/lifecycle mechanism, theme, or other portable behavior, move it to the canonical Arcane SDK or document the specific ownership exception.

For visual work, reviewers must also confirm that the Arcane theme is the first layer, the user's saved appearance is applied, app and component CSS follows the shared layer, and overrides do not defeat user taste, accessibility, or cross-app consistency.

For setup, build, package, test, model, app, or runtime work, reviewers compare the implementation to the recorded multiplier and cold-path measurement. A change is not ready when invariant OS-owned work appears inside an app loop, expensive operations exceed the justified count, reusable work lacks a clear invalidation rule, or progress UI merely makes redundant work visible.

Reviewers must also reject foreground blocking hidden behind async/await, delayed UI or CLI acknowledgement, unbounded fan-out, missing backpressure, silent fire-and-forget tasks, progress without a heartbeat during opaque waits, unsafe cancellation, or broad serialization that begins before visible status.

For AI, corpus, cancellation, and terminal-workflow changes, reviewers reject app-built provider payloads, positional request APIs in new code, ambiguous structured-output semantics, unrecorded app-side generation options or byte/token heuristics, model-rewritten retrieval queries, manifest-defined or truncated DBOPFS corpora, serial or all-or-nothing group handling, estimated-file progress, warning text in model prompts, and diagnostics that truncate ordinary prompt/body content beyond exact credential, protected-data, or privacy exclusions.

Reviewers must trace one page-owned signal through every transport and confirm abort stops the provider's actual upstream work as well as local effects. A change is not ready when detach can leave a queued group, retry, continuation, timer, persistence callback, or UI mutation alive.

For terminal closeout, reviewers confirm the tool remains available until successful completion, the trigger is semantic rather than keyword-based, the sole call parses to one complete final message, remembered actions receive separate consent, no-link messages remain valid, one semantic response-purpose decision is consumed, the terminal transcript commits before controls disappear, and every post-close submission path is rejected.

Reviewers must also reject scattered semantic-policy booleans, duplicate normalization, app-local copies of shared provider or terminal mechanisms, direct node:test imports, private vanilla lifecycles, automatic tests/checks, and unconditional all-app package/native/signing work. The selected artifact boundaries must match the actual delivery claim.

Repository and reviewed source access