import type { ProjectType, ScaffoldInputs } from "./index.js"; import { type SubstitutionOptions } from "./substitute.js"; export type StandardKey = "skill-vault" | "portable-stack" | "fathom" | "uptime-kuma" | "sentry" | "service-hosting" | "neon-careful" | "temp-files" | "agent-coordination" | "seo-baseline" | "email-service" | "moderation" | "card-path-bot-protection" | "text-size" | "test-count"; export type StandardDecisionState = "inserted-inline" | "skipped-not-applicable" /** * Applicable, rendered β€” and then removed again, because the audience gate * dropped the whole `## ` section it lives in for `audience: "external"`. * * πŸ”΄ **A third state, rather than leaving it `inserted-inline`, because the * two-state version made a consumer's UI tell a customer something false.** * `resolveStandards()` is a pure function that runs BEFORE the gate, so its * verdict is "this standard applies and was rendered into the body" β€” true * when written and still true. The gate then removes the section holding it. * Neither half is individually wrong, which is exactly why no unit test * caught it: `project-creator`'s preview screen reported an outside customer * *"Skill Vault awareness"* β€” a standard whose entire content is "there is a * private Z2W skill library at this path" β€” for a `CLAUDE.md` that no longer * mentions it (filed 2026-08-19). * * Set by the writer from the gate's ACTUAL `dropped` list, never recomputed * from the audience β€” a second derivation of the same fact is a second thing * to drift. */ | "removed-by-audience-gate"; export interface StandardDecision { key: StandardKey; title: string; state: StandardDecisionState; /** Why the conditional matched (or didn't). */ reason: string; /** * For `removed-by-audience-gate` only: the `## ` heading the gate dropped * that took this standard's text with it. Named rather than implied, so a * consumer can say *which* section went and does not have to know the * standardsβ†’section mapping to render an honest log. */ removedFromSection?: string; } export interface ResolveStandardsOptions extends SubstitutionOptions { /** * When true, signals the writer (ROADMAP Step 6) to run an interactive * (a) inline / (b) promote-into-Templates dialog per applicable standard * before the final write. The resolver itself remains pure-functional: * it produces the default-(a) inline body and surfaces * {@link StandardsResolution.promotePending} so the writer knows to * defer for the dialog. Default false β€” paid subscribers shouldn't be * forced through four dialogs per scaffold. */ promoteStandards?: boolean; } export interface StandardsResolution { /** * Markdown body suitable for `.replace()`-ing into the * `` marker that the Step 4 scaffolders emit * inside CLAUDE.md. Already includes substitutions; ready to write. */ body: string; /** * The verbatim canonical Agent Coordination section, ready to `.replace()` * into the `` marker (a TOP-LEVEL `## Agent * Coordination` section, kept OUT of the `## Standards block` so it can carry * the canonical heading + fingerprint comment verbatim). Empty string when * the project does not participate in the bulletin. */ agentCoordinationBody: string; /** One entry per standard the resolver considered (applicable or not). */ decisions: StandardDecision[]; /** * True iff `opts.promoteStandards` was set. Forwarded to the writer so the * interactive a/b dialog runs at the writer phase, not here. */ promotePending: boolean; } /** * Fathom env var name per framework. Mirrors skill v1.1.0's Step 6 conditional * wording: `NEXT_PUBLIC_FATHOM_SITE_ID` for Next.js, hard-coded inline for * cf-pages static HTML, `PUBLIC_FATHOM_SITE_ID` for the Vite/SvelteKit/Astro * family β€” the safe default for anything else with `has_web_ui=true`. */ export declare function fathomEnvVarFor(projectType: ProjectType): string; export declare const CANONICAL_COORDINATION_BLOCK_VERSION = "v0.1.34"; /** * The canonical **Capture Learnings** block, emitted VERBATIM into every * scaffolded `CLAUDE.md`. * * Owned by `zero2webmaster/cursor-project-templates`; canonical source is * `Resources/CAPTURE_LEARNINGS_BLOCK.md` in the Templates folder this CLI * already reads (OP #1). Do NOT paraphrase it here β€” the paraphrase is the * failure mode this block exists to prevent, exactly as it was for the Agent * Coordination block, and `capture-learnings.test.ts` byte-diffs the two. * * Why it must be emitted into CLAUDE.md rather than left in the framework body: * the step was canonical from framework v2.13.0 but lived only in `AGENTS_v*.md`, * which is NOT loaded into agent context. 25 of 41 Z2W projects were measured * missing it on 2026-07-27 β€” including every project this CLI has scaffolded. * Reported as an ACTION by `z2w-observability-bridge` (2026-07-27); closed here. */ export declare const CAPTURE_LEARNINGS_BLOCK_VERSION = "v1.2.0"; /** * The literal markdown heading each standard renders, keyed by `StandardKey`. * * Exists so a test can compare THIS CLI's standard set against the * [[instantiate-z2w-project]] skill's `references/standards-block.md` in the * skill β†’ CLI direction. That direction had never been checked: OP #2's mirror * habit propagates CLI changes INTO the skill, so a standard that existed only * in the skill was invisible to every guard here. `temp-files` sat in that blind * spot for months (found 2026-08-05) β€” the skill's Step 6 list named it, the * reference file carried a full body for it, and `git log -S` proves this CLI * never had it. Derived from `BODIES` rather than restated, so it cannot drift * from what actually renders. */ export declare function standardHeadings(): Record; /** * Resolve which standards apply to `inputs` and render the standards markdown * body suitable for `.replace()`-ing into the `` * marker that the Step 4 scaffolders emit inside CLAUDE.md. * * Pure function: no filesystem reads, no time-of-day dependencies (date can * be pinned via {@link ResolveStandardsOptions.date} for snapshot tests). */ export declare function resolveStandards(inputs: ScaffoldInputs, opts?: ResolveStandardsOptions): StandardsResolution; /** * Convenience: take the CLAUDE.md content emitted by a Step 4 scaffolder and * replace the `` marker with the resolver's body. * Callers that compose the standards body with the rest of the writer pipeline * can use this directly; tests use it to verify the full integration end-to-end. * * Returns the input verbatim if the marker isn't present (so this is safe to * call on any file). */ export declare function applyStandardsBlock(claudeMd: string, resolution: StandardsResolution): string; /** * Wrap a replacement so `String.replace()` inserts it LITERALLY. * * πŸ”΄ Never pass canonical prose to `.replace()` as a replacement *string*. JS * interprets `$&`, `` $` ``, `$'`, `$1` and `$$` inside a replacement string as * special patterns, and the bodies spliced by this module are hand-written * markdown from upstream sources we do not control β€” so any of those sequences * can appear at any time without warning. * * This is not hypothetical. Protocol v0.1.25 / block v0.1.18 (2026-07-30) added * the sentence ``Anchor the rewrite on the heading as a whole LINE (`^## Current * focus$`)`` β€” whose `$` + closing backtick form the two-byte sequence `` $` ``, * meaning "everything in the subject string BEFORE the match". Every scaffold * emitted after that date spliced its own ENTIRE document head back into the * middle of the coordination block: `marketing-engine`'s committed `CLAUDE.md` * came out at 1522 lines with two `# Agent Instructions` headings, and the * sentence carrying the `$` was truncated mid-clause. * * It was silent in every channel that could have caught it. The byte-diff test * compares the CONSTANT against `AGENT_PROTOCOL.md` and passed β€” the constant * was always correct; the *emission* was corrupt. Nothing reads a scaffolded * `CLAUDE.md` as part of a build, so there was no downstream error either. A * replacer FUNCTION's return value is used verbatim, with no `$` interpretation * at all, which is why this is the fix rather than escaping `$$`. */ export declare function literalReplacement(text: string): () => string; /** * Fill the `` marker with the verbatim * canonical Agent Coordination section (or remove it, leaving a clean seam, * when the project does not participate in the bulletin). Kept separate from * {@link applyStandardsBlock} because the section is a TOP-LEVEL `## Agent * Coordination` block that must sit outside `## Standards block`. * * Returns the input verbatim if the marker isn't present (safe on any file). */ export declare function applyAgentCoordinationBlock(claudeMd: string, resolution: StandardsResolution): string; /** * Fill the `` marker with the verbatim canonical * Capture Learnings block. * * UNCONDITIONAL, unlike {@link applyAgentCoordinationBlock} β€” the step applies to * every Z2W project regardless of bulletin participation, DB, or web UI. It is a * top-level `##` section, so it sits outside `## Standards block`. */ export declare function applyCaptureLearningsBlock(claudeMd: string): string;