import { type ScaffoldInputs } from "./index.js"; /** Airtable REST API root. */ export declare const AIRTABLE_API_BASE = "https://api.airtable.com/v0"; /** * The marker the scaffolder actually writes when the agent-coordination * standard applies. As of the verbatim-canonical-block change (v0.4.0), a * scaffolded project DOES carry the real `` HTML fingerprint — the same token cross-project * drift detection (Signal A) greps for — so a fresh scaffold passes drift * detection with no manual first-session re-sync. We grep-verify against that * fingerprint, with the block's lead sentence retained as a fallback for older * scaffolds that predate the fingerprint emission. */ export declare const COORDINATION_BLOCK_MARKER: RegExp; /** * "Verify, don't assert" (mirrors [[github-readme-and-version-integrity]]). * Read the freshly-written scaffold and report whether it actually carries the * agent-coordination block, so the Airtable write only claims * `Agent Coordination = Registered` when the block is really present. * * The standards block (including the coordination body) is inserted into * CLAUDE.md; AGENTS.md is checked as a fallback (it mirrors CLAUDE.md). Safe * failure mode: a missing/unreadable scaffold returns `false`, which leaves the * column blank for Kerry rather than asserting a state we couldn't confirm. */ export declare function scaffoldCarriesCoordinationBlock(targetPath: string, opts?: { readFileImpl?: (path: string) => Promise; }): Promise; /** "Cursor Projects" base. Override with AIRTABLE_INVENTORY_BASE_ID. */ export declare const DEFAULT_INVENTORY_BASE_ID = "appomsRpbA3oOlcaW"; /** * "Projects" table — the table ID (not the display name) so the code survives * a table rename. Override with AIRTABLE_INVENTORY_TABLE. */ export declare const DEFAULT_INVENTORY_TABLE = "tblRoXwwu8wzvfqVY"; export interface AirtableConfig { pat: string; baseId: string; table: string; } /** * Resolve Airtable config from the environment. Returns null when no * AIRTABLE_WRITE_PAT is set — the signal that auto-registration is disabled * for this caller (every CLI user who isn't Kerry). The base/table fall back * to the live "Cursor Projects" defaults when not overridden. */ export declare function resolveAirtableConfig(env?: NodeJS.ProcessEnv): AirtableConfig | null; /** * Derive a human-friendly project display name from a slug. * `z2w-crowdcommerce` → "Z2W Crowdcommerce"; `org-hq` → "Org HQ". * * Best-effort and intentionally so: this is the SEED for a new row's * `project_name`, not an attempt to reproduce a curated one. 43 of the 96 * registry names carry editorial content no slug contains — "Femperium Web * Scraping / Lead Gen", "Static Sites For Small Businesses" — which is why * `project_name` is insert-only rather than better-computed. */ export declare function displayNameFromSlug(slug: string): string; export type AirtableFields = Record; export interface BuildProjectFieldsOptions { /** * Whether the freshly-written scaffold was confirmed to carry the * coordination block (see `scaffoldCarriesCoordinationBlock`). When this is a * boolean, it gates the `Agent Coordination = Registered` assertion — "verify, * don't assert". When `undefined` (the caller couldn't verify — e.g. a * dry-run with nothing on disk, or a direct unit-test call), we fall back to * the `participateInBulletin` input flag alone. */ coordinationVerified?: boolean; } /** * Pure mapping from ScaffoldInputs to the Airtable "Projects" row fields. * Column names confirmed by Kerry 2026-06-03 / 2026-06-16. Columns left empty * for Kerry (WordPress Agents File, Framework Version, Plan, Project Type, …) * are intentionally omitted. */ export declare function buildProjectFields(inputs: ScaffoldInputs, opts?: BuildProjectFieldsOptions): AirtableFields; export type RegisterOutcome = "created" | "dry-run" | "skipped" | "failed"; export interface RegisterResult { outcome: RegisterOutcome; /** The fields that were (or would be) written. */ fields: AirtableFields; /** Created Airtable record id, when outcome === "created". */ recordId?: string; /** The POST target URL (never contains the token). */ url?: string; /** Human-readable, secret-free line for the CLI to surface. */ message: string; /** * Result of the on-disk coordination-block check, when it ran (i.e. a * participating scaffold with a `targetPath`, not a dry-run). `undefined` * when verification was not attempted. */ coordinationVerified?: boolean; } export interface RegisterOptions { env?: NodeJS.ProcessEnv; /** Test/override seam for the HTTP client. Defaults to global fetch. */ fetchImpl?: typeof fetch; /** Build the request but do not POST — for `init --dry-run`. */ dryRun?: boolean; /** * Override config explicitly (tests). When provided (including `null`), * bypasses env resolution. `null` forces the "skipped" path. */ config?: AirtableConfig | null; /** * Absolute path to the freshly-written scaffold. When provided (and not a * dry-run) for a participating project, the coordination block is * grep-verified on disk before `Agent Coordination = Registered` is asserted. */ targetPath?: string; /** Test seam for the filesystem read used by coordination verification. */ readFileImpl?: (path: string) => Promise; } /** * Create the inventory row for a freshly-scaffolded project. Warn-and-proceed: * always resolves (never rejects); the CLI surfaces `message` and continues. * * - No AIRTABLE_WRITE_PAT → outcome "skipped" (silent for normal users). * - opts.dryRun → outcome "dry-run" (prints the would-be request). * - 2xx → outcome "created" (+ recordId). * - non-2xx / network err → outcome "failed" (+ a diagnostic; row NOT created). */ export declare function registerProjectRow(inputs: ScaffoldInputs, opts?: RegisterOptions): Promise;