Here is the output of an architectural discussion I had with an AI mode agent on google online. This was out-of-band (i.e. not in Antigravity), but here is the summary of ideas for when we implement a simplified AES wrapper here in encrypt-gib.

As I understand it, the greatest gains we could make involve changing the "String Variant" (where we convert to/from, pass around, and concatenate a bunch of strings) and the "Byte Variant" (where we stay working with byte arrays instead of doing all of the string conversions/etc.).

We will want to discuss these ideas and others when executing on both the AES and other strategies incorporated in encrypt-gib's API.

---

# Roadmap & Architectural Refactor Specification

This document outlines two major structural initiatives for `encrypt-gib`:
1. **Simplified AES Wrapper Integration:** Exposing highly accessible Web Crypto AES configurations through the core library interface.
2. **High-Throughput Byte-Variant Strategy:** Implementing a zero-allocation, allocation-free binary pipeline alongside our highly readable, string-based reference implementation.

---

## Part 1: AES Simplified Interface Wrapper

**Objective:** Allow users to utilize `encrypt-gib` as a straightforward interface to simplified Web Crypto AES settings, minimizing cognitive load for developers who want a production-hardened algorithm without managing complex initialization vector (IV) mechanics manually.

### Conceptual Implementation Skeleton

Just a rough sketch, we don't have to follow this exactly.

```typescript
/**
 *  what is required for post-quantum? We may want factory methods/parameter
 *  sets or something for convenient collections of parameters.
 */
export interface AESWrapperOptions {
    secret: string;
    salt?: string;
    algorithm?: 'AES-GCM' | 'AES-CBC';
    length?: 128 | 192 | 256;
}

/**
 * Simplified AES wrapper interface.
 * Handles key derivation (PBKDF2) and block mode configuration under the hood.
 */
export class AESEngine {
    private keyPromise: Promise<CryptoKey>;

    constructor(options: AESWrapperOptions) {
        this.keyPromise = this.deriveKey(options.secret, options.salt || 'default-salt', options.length || 256);
    }

    private async deriveKey(secret: string, salt: string, length: number): Promise<CryptoKey> {
        const baseKey = await globalThis.crypto.subtle.importKey(
            "raw", new TextEncoder().encode(secret), "PBKDF2", false, ["deriveKey"]
        );
        return globalThis.crypto.subtle.deriveKey(
            { name: "PBKDF2", salt: new TextEncoder().encode(salt), iterations: 100000, hash: "SHA-256" },
            baseKey, { name: "AES-GCM", length }, true, ["encrypt", "decrypt"]
        );
    }

    export async function encrypt(plaintext: string): Promise<{ ciphertext: string, iv: string }> {
        const key = await this.keyPromise;
        const iv = globalThis.crypto.getRandomValues(new Uint8Array(12)); // Standard 96-bit IV for GCM

        const encryptedBuffer = await globalThis.crypto.subtle.encrypt(
            { name: "AES-GCM", iv }, key, new TextEncoder().encode(plaintext)
        );

        return {
            ciphertext: btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer))),
            iv: btoa(String.fromCharCode(...iv))
        };
    }
}
```

---

## Part 2: The Core JIT Algorithm "Byte Variant" Optimization

**Objective:** Transition the internal recursive hashing loop from mutating JavaScript heap strings (`string` arrays, `.join()`, `+` operations) to manipulating strict binary `Uint8Array` allocations. This eliminates V8 string garbage collection pauses completely while remaining 100% isomorphic.

### Architectural Strategy Pattern

We will preserve the simple string-concatenation engine as the reference standard (`strategy: 'string-variant'`), while introducing a performance runtime path (`strategy: 'byte-variant'`).

```typescript
export type ProcessingStrategy = 'string-variant' | 'byte-variant';
```

### 1. Zero-Allocation `getPreHashBytes` vs. String Concatenation

Instead of copying strings and parsing character data continuously, bytes are layered cleanly into a single target buffer array before hitting `subtle.digest`.

```typescript
// OLD WAY: Highly readable but causes massive V8 string heap churn
// return salt + (prevHash || secret);

// NEW WAY: Byte-Variant alignment with zero string allocations
export function getPreHashBytes({
    secretBytes, prevHashBytes, saltBytes, saltStrategy
}: {
    secretBytes?: Uint8Array, prevHashBytes?: Uint8Array, saltBytes: Uint8Array, saltStrategy: SaltStrategy
}): Uint8Array {
    const coreBytes = prevHashBytes || secretBytes;
    const totalLength = saltBytes.length + coreBytes!.length;
    const out = new Uint8Array(totalLength);

    if (saltStrategy === SaltStrategy.prependPerHash) {
        out.set(saltBytes, 0);
        out.set(coreBytes!, saltBytes.length);
    } // ... handle append/initial states identically
    return out;
}
```

### 2. Eliminating the Asynchronous Inner Loop String-Building Tax

Instead of accumulating a hex string (`alphabet += hash`) and running `.indexOf()`, the Byte Variant tracks alphabet presence via a tiny fixed lookup table directly in Web Crypto's raw output array format.

```typescript
// CONCEPTUAL BYTE ENGINE HOT-LOOP RUNTIME
// Loops through the byte-stream data directly, bypassing hex translation overhead

let prevHashBytes: Uint8Array = initialStretchedBytes;
const encryptedIndices = new Uint32Array(rawPlaintextBytes.length);

for (let i = 0; i < rawPlaintextBytes.length; i++) {
    const targetByte = rawPlaintextBytes[i]; // Isolated instantly as a 0-255 integer
    let charFound = false;
    let localIndex = -1;

    while (!charFound) {
        // 1. Generate next hash directly as raw bytes (no Hex LUT formatting yet)
        const preHashInput = getPreHashBytes({ prevHashBytes, saltBytes, saltStrategy });
        const arrayBuffer = await globalThis.crypto.subtle.digest(hashAlgorithm, preHashInput);
        const currentHashBytes = new Uint8Array(arrayBuffer);

        // 2. Scan the byte array natively for our integer target
        localIndex = currentHashBytes.indexOf(targetByte);
        if (localIndex !== -1) {
            charFound = true;
        }
        prevHashBytes = currentHashBytes;
    }

    encryptedIndices[i] = localIndex;
}

// Final transformation converts the Uint32Array directly into a Base64 or
// flat Hex string block at the absolute last moment before exit.
```

---

## Summary of Agent Discussion Targets

When instructing an autonomous development agent inside Antigravity, focus issues around these exact criteria:
* **Interface Uniformity:** Ensure both the native recursive JIT engine and the new AES Wrapper share identical entry/exit options where possible.
* **Isomorphic Integrity:** Ensure that the `Uint8Array` arrays never use Node-exclusive `Buffer` globals to keep browser compatibility pristine.
* **Verification Parity:** Verify that `strategy: 'byte-variant'` generates mathematical outputs that map accurately back onto the primitive values verified by `strategy: 'string-variant'`.
