/** * How a project's stable identity is SPELLED. The rule, once, for everyone who has to produce it. * * projectId is what scopes a session to an app, so the build plugin's stamp and what `reticle init` * records into `.reticle.json` have to agree exactly or the app's sessions land under a project * nobody is looking at. It was maintained as two byte-identical copies — `slugifyPackageName`, * `shortHash` and `deriveProjectId` in both `@reticlehq/vite-plugin` and `@reticlehq/server` — held * in sync by a comment asking the next contributor to keep them identical. They still were, but * nothing would have failed on the day they were not: no test compares them, and the symptom of a * mismatch is a session quietly filed under the wrong id. * * The hashing stays with the callers because it needs `node:crypto`, and core is isomorphic — the * same split `discoverDaemonPort` already uses, where core owns the selection rule and each package * owns its own filesystem plumbing. */ /** How much of the digest goes into the id. Short enough to read, long enough not to collide. */ export declare const PROJECT_ID_HASH_LENGTH = 8; /** `@acme/web` → `acme-web`; non-alphanumerics collapse to single dashes; edges trimmed. */ export declare function slugifyPackageName(name: string): string; /** * The stable projectId: a slug of the package name (falling back to the root's folder name, then * `app`), plus a short fingerprint of the absolute root so two checkouts of the same package are * still distinct. * * `hash` is injected rather than imported — it is the one impure, Node-only part, and passing it in * is what lets this rule live in the isomorphic package with the callers that own `node:crypto`. */ export declare function projectIdFrom(pkgName: string | undefined, rootPath: string, hash: (input: string) => string): string;