export declare const WORKSPACE_MANIFEST = "pnpm-workspace.yaml"; export declare const PACKAGE_MANIFEST = "package.json"; export declare const MANIFEST_FILENAMES: ReadonlySet; export declare const CAPTURE_TAIL_ERE = "([[:space:]]+2>(&1|/dev/null))?([[:space:]]*\\|[[:space:]]*(tail|head)([[:space:]]+-(n[[:space:]]+)?[0-9]+)?)?[[:space:]]*$"; export declare const CAPTURE_TAIL_JS_SRC = "(\\s+2>(&1|\\/dev\\/null))?(\\s*\\|\\s*(tail|head)(\\s+-(n\\s+)?[0-9]+)?)?\\s*$"; export declare const CD_PREFIX_ERE = "(cd[[:space:]]+([A-Za-z0-9._/@~+-]+|'[^']+')[[:space:]]*&&[[:space:]]*)?"; export declare const CD_PREFIX_JS_SRC = "(cd\\s+([A-Za-z0-9._\\/@~+-]+|'[^']+')\\s*&&\\s*)?"; export declare const INSTALLER_ALLOW_ERE: string; export declare const INSTALLER_ALLOW_JS: RegExp; export declare const RECOVERY_ALLOW_ERE: string; export declare const RECOVERY_ALLOW_JS: RegExp; export declare const RECOVERY_CMD = "rm -rf node_modules && pnpm install"; export declare const FETCH_ALLOW_ERE: string; export declare const FETCH_ALLOW_JS: RegExp; export declare const CHECKOUT_MAIN_PULL_ALLOW_ERE: string; export declare const CHECKOUT_MAIN_PULL_ALLOW_JS: RegExp; /** * The exact bytes every L0 message prescribing the on-main sync must print. * * L0 ONLY. The workflow guards prescribe `pnpm wp-checkout-clean-main`; this constant is for the faults * where `node_modules` is the thing under suspicion and no `pnpm` bin can be relied on to run. See the * block comment above CHECKOUT_MAIN_PULL_BODY_ERE for the full argument, and do not "unify" the two. */ export declare const CHECKOUT_MAIN_PULL_CMD = "git checkout main && git pull origin main"; export declare const UPGRADE_SHIM_ALLOW_ERE: string; export declare const UPGRADE_SHIM_ALLOW_JS: RegExp; export declare const UPGRADE_SHIM_CMD = "pnpm exec wp-upgrade-shim"; export declare const RESTORE_SHIM_ALLOW_ERE: string; export declare const RESTORE_SHIM_ALLOW_JS: RegExp; export declare const RESTORE_SHIM_CMD = "cp node_modules/@webpieces/ai-hook-rules/templates/ai-hook.sh .claude/webpieces/ai-hook.sh"; export declare const INSTALL_HOOKS_ALLOW_ERE: string; export declare const INSTALL_HOOKS_ALLOW_JS: RegExp; export declare const ADD_HOOK_PKG_ALLOW_ERE: string; export declare const ADD_HOOK_PKG_ALLOW_JS: RegExp; /** The package every wp-ai-* bin ships in — the one name fault U is about. */ export declare const HOOK_PKG = "@webpieces/ai-hook-rules"; /** The version-less spelling of the fault-U cure; the deny appends `@` when it can infer one. */ export declare const ADD_HOOK_PKG_CMD = "pnpm add -D @webpieces/ai-hook-rules"; export declare const ORIENT_ALLOW_ERE: string; export declare const ORIENT_ALLOW_JS: RegExp; export declare const ORIENT_CMD = "pwd"; export declare const INSTALL_HOOKS_CMD = "pnpm exec wp-install-ai-hooks"; export declare const INSTALL_HOOKS_TARGET_CMD = "pnpm wp-install-ai-hooks --target=project"; /** One tool call as L0 judges it: the tool name, the Bash command (or ''), the file target (or ''). */ export declare class L0Call { readonly toolName: string; readonly command: string; readonly filePath: string; constructor(toolName: string, command: string, filePath: string); } /** * One entry of THE L0 allowlist. Data-only → a class, per CLAUDE.md. * * `ere`/`js` are the twin regex BODIES for a Bash entry, or null for a tool-shaped entry (Read, the * webpieces.config.json target) that no regex can express. `sample` is a call this entry must accept — * it is what the matrix-coverage and cure-reachability tests drive isAllowed() with. * * `extraSamples` pins ADDITIONAL spellings the same entry must accept. A spelling that some deny * message prescribes belongs here, or nothing stops a later tightening of the pattern from making that * message's cure untypable again — which is the deadlock shape this whole module exists to prevent. * * `cure` is the ONE thing that is not uniform across the list, and it is not about L0 at all — see * L0_CURE_ALLOW_JS below. Every entry is judged identically while an L0 fault is up; `cure` decides * only whether the entry ALSO bypasses the downstream (L1) guards on a HEALTHY tree. */ export declare class L0AllowEntry { readonly label: string; readonly kind: 'pass' | 'allow'; /** * True when this entry REPAIRS the tooling (install, sync, shim restore). A cure has to run * before webpieces.config.json can even be loaded, so it bypasses everything, always. A * non-cure (read-only orientation) is allowed while a fault is up and is otherwise an ordinary * command the downstream guards still judge. */ readonly cure: boolean; readonly ere: string | null; readonly js: string | null; readonly sample: L0Call; readonly extraSamples: readonly L0Call[]; constructor(label: string, kind: 'pass' | 'allow', /** * True when this entry REPAIRS the tooling (install, sync, shim restore). A cure has to run * before webpieces.config.json can even be loaded, so it bypasses everything, always. A * non-cure (read-only orientation) is allowed while a fault is up and is otherwise an ordinary * command the downstream guards still judge. */ cure: boolean, ere: string | null, js: string | null, sample: L0Call, extraSamples?: readonly L0Call[]); /** Every call this entry pins: the canonical sample plus every extra spelling. */ allSamples(): readonly L0Call[]; } export declare const L0_ALLOWLIST: readonly L0AllowEntry[]; export declare const L0_ALLOW_ERE: string; export declare const L0_ALLOW_ERE_SH: string; export declare const L0_ALLOW_JS: RegExp; export declare const L0_CURE_ALLOW_JS: RegExp; export declare const READ_TOOLS: ReadonlySet; /** * `isAllowed(call)` — THE L0 allowlist, with no fault parameter. See the block comment above. * * Returns the OUTCOME KIND, because the two are not the same thing: * - 'pass' → L0 has no objection; fall THROUGH so L1/L2 still judge this call (Read, config edit). * - 'allow' → terminal; bypass everything, because a cure must stay reachable even when a downstream * guard would block it. * - null → not on the list. * * `CONFIG_FILENAME` stays a basename match on purpose — one per tree; narrowing it is its own question. */ export declare function isAllowed(toolName: string, command: string, filePath: string): 'pass' | 'allow' | null; /** * Is `filePath` the `package.json` / `pnpm-workspace.yaml` at the ROOT OF A GOVERNED TREE — the only two * files the version cure ever edits? * * AS WIDE AS THE CURE AND NO WIDER. A basename match would put EVERY project, app and library * `package.json` on the L0 allowlist, and at L0 that is worse than it sounds: the sh half treats a hit * as TERMINAL (`exit 0`, the guard bin never runs), so each of those would be editable under fault * D/X/U/K with nothing downstream judging it. BUT IT MUST ADMIT EVERY TREE, not one — a worktree * agent's cure edits ITS OWN root manifest, and the shim's `$ROOT` names whichever tree supplied the * shim (governingShimRoot's straddle), so neither a basename nor a fixed root is the right test. * * The test is: its own directory must ALSO hold a `webpieces.config.json`. That file is TRACKED, so the * main clone has one and every linked worktree has its own — the same definition `runner.ts` uses * (`dirname(configPath)`), without knowing which tree you stand in. A project manifest deep under * `packages/` has no config beside it and is excluded. The sh twin is one `[ -f ... ]` test. */ export declare function isRootManifest(filePath: string): boolean;