/** * The single canonical derivation of a project's **routing pin** and its **deterministic local * port** from the project root path — the TypeScript port of the shared .NET reference * `com.IvanMurzak.McpPlugin.AgentConfig.ProjectIdentity` * (`MCP-Plugin-dotnet/McpPlugin/src/AgentConfig/ProjectIdentity.cs`). Every runtime (the * Unity/Godot/Unreal plugins, the .NET sidecar, and the three engine CLIs) derives identical * values with no shared state and no probing, so an agent session launched in a project folder * routes strictly to that project's engine instance. * * Two normalizations are shipped side by side (auth-fixes design 02 T3 / defect B5): * * - **v1** (`normalize` / `derivePin` / `derivePort` / `deriveProjectPathHash`) — the legacy * algorithm, kept verbatim so old `.mcp.json` pins keep matching during the dual-hash * transition (decision M1). Separators are NOT converted: `C:\a` and `C:/a` hash differently. * - **v2** (`normalizeV2` / `derivePinV2` / `derivePortV2` / `deriveProjectPathHashV2`) — the * new algorithm the configurators now emit. It adds ONE step to the v1 normalization — * converting `\` to `/` — so a Windows project root reported with backslashes (`C:\a\b`) and * the same root reported with forward slashes (`C:/a/b`) hash IDENTICALLY. That kills B5. * * Cross-language parity (C# vs TS) is gated byte-for-byte by the committed golden-vector files * (`ProjectIdentity.GoldenVectors.json` v1 and `ProjectIdentity.GoldenVectors.v2.json` v2), * vendored under `test/golden-vectors/` and reproduced by `test/project-identity.test.ts`. The * files also pin the one Unicode divergence that matters for real paths — U+0130 (see * {@link toLowerInvariant}). * * Algorithm (v1; v2 inserts the `\`→`/` substitution at step 2): * 1. Trim trailing directory separators (`/` and `\`) so `/a/b` and `/a/b/` are the same project. * 2. Lowercase with an invariant fold (`ToLowerInvariant`-equivalent — see {@link toLowerInvariant}). * 3. UTF-8 encode, then SHA-256 hash. * 4. pin = the first 4 bytes of the hash as 8 lowercase hex chars. * 5. port = 20000 + (littleEndianUInt32(first 4 bytes) % 10000). Range 20000-29999. */ /** Inclusive lower bound of the deterministic local-port range. */ export declare const MIN_PORT = 20000; /** Inclusive upper bound of the deterministic local-port range. */ export declare const MAX_PORT = 29999; /** Number of ports in the deterministic range (10000). */ export declare const PORT_RANGE: number; /** Number of hex characters in the routing pin (first 4 bytes of the hash). */ export declare const PIN_LENGTH = 8; /** * Lowercase a string the way .NET `string.ToLowerInvariant()` does: a simple, culture-independent, * per-code-point mapping (no context-sensitive rules such as the Greek final-sigma or the * Turkish-i special cases). Each code point is lowered on its own; {@link INVARIANT_LOWER_OVERRIDES} * corrects the few points where JS disagrees with .NET. */ export declare function toLowerInvariant(value: string): string; /** The resolved identity for a project root (pin + resolved port). */ export interface ProjectIdentity { /** The routing pin: first 8 lowercase hex chars of the SHA-256 of the normalized project root. */ pin: string; /** The resolved local port — the hash-derived port unless an explicit override was supplied. */ port: number; /** True when {@link ProjectIdentity.port} came from an explicit user override rather than the hash. */ portIsOverridden: boolean; } /** * The v1 pre-hash string: the project root with trailing directory separators trimmed, then * invariant-lowercased. Separators are NOT converted — `C:\a` and `C:/a` stay distinct. */ export declare function normalize(projectRoot: string): string; /** The v1 routing pin (first 8 lowercase hex chars of the hash). Never affected by overrides. */ export declare function derivePin(projectRoot: string): string; /** The v1 hash-derived port (ignores any override). Range 20000-29999. */ export declare function derivePort(projectRoot: string): number; /** * The FULL v1 project-path hash: the complete 64-char lowercase hex SHA-256 of the normalized * project root — the legacy `projectPathHashLegacy` an engine plugin sends in its hub * instance-metadata handshake. The v1 routing pin is a case-insensitive prefix of this value. */ export declare function deriveProjectPathHash(projectRoot: string): string; /** * Derive the v1 identity for `projectRoot`. When `portOverride` is non-null (the user's explicit * override from the project marker) it always wins for {@link ProjectIdentity.port}; the * {@link ProjectIdentity.pin} is always hash-derived. */ export declare function deriveProjectIdentity(projectRoot: string, portOverride?: number | null): ProjectIdentity; /** * The v2 pre-hash string: the project root with trailing directory separators trimmed, every * backslash converted to a forward slash, then invariant-lowercased. This single primitive backs * the v2 pin, the full v2 project-path hash, and the v2 deterministic port — so a Windows root * reported with `\` and the same root with `/` derive identically (the B5 fix). */ export declare function normalizeV2(projectRoot: string): string; /** The v2 routing pin (first 8 lowercase hex chars of the SHA-256 of {@link normalizeV2}). */ export declare function derivePinV2(projectRoot: string): string; /** The v2 hash-derived port (ignores any override). Range 20000-29999. */ export declare function derivePortV2(projectRoot: string): number; /** * The FULL v2 project-path hash (64-char lowercase hex of the SHA-256 of {@link normalizeV2}) — * the `projectPathHash` an engine plugin sends in its hub instance-metadata handshake. The v2 * routing pin is a case-insensitive prefix of this value by construction. */ export declare function deriveProjectPathHashV2(projectRoot: string): string; /** * Derive the v2 identity for `projectRoot`. When `portOverride` is non-null it always wins for * {@link ProjectIdentity.port}; the {@link ProjectIdentity.pin} is always hash-derived. */ export declare function deriveProjectIdentityV2(projectRoot: string, portOverride?: number | null): ProjectIdentity; //# sourceMappingURL=project-identity.d.ts.map