Generated Files
init prints every planned action before or as it applies it. The exact set depends on the current project, topology, configured emit paths, selected Agent, and whether Blueprint can safely merge an existing integration. --dry-run is the authoritative preview for one repository:
npx @kekkai/blueprint init --topology layer-first --dry-runThis page separates three kinds of effects:
- durable Blueprint configuration and outputs;
- temporary authoring, transformation, or upgrade handoffs;
- existing project files that
initmay update.
The same ownership rules decide what remove deletes, strips, reverses, or keeps when Blueprint is de-adopted.
Durable configuration and outputs
blueprint.config.mjs
Why it exists: it is the architecture authority after adoption.
What it contains: framework, source root, layer-first or module-first structure, dependency and ownership rules, project doctrine, and output policy. See Configuration.
Ownership: the adopter owns the architecture decisions. Blueprint may scaffold a known preset, but an authored config is never silently replaced by a preset or by folder inference.
Lifecycle: a preset path creates it, including the empty module-first runway for a proven-empty application. An authoring playbook instructs the Agent to create it. Later init runs load and validate it before refreshing outputs. A Blueprint 3.2 config is first normalized to the supported 4.0 layer-first shape as a recoverable checkpoint; an opposite-topology request requires a later guarded transformation run from that checkpoint. The normalization edits the config's own source: it removes architecture.module and each layer's module, and adds layout / entry only where the migrated value differs from the 4.x default. Preset calls, defineBlueprint, comments, and every other byte stay as written. Before rewriting, init saves the complete original beside it as blueprint.config.mjs.pre-v4-<sha256> (including comments). The write notice warns that architecture.module.private has no 4.0 replacement: review the original policy before claiming equivalent governance. The backup is owner evidence, not a loaded config. When those keys are not literal properties of the config (built in a helper, spread in, or computed), init leaves the file byte-identical, writes no backup, and names the keys to rewrite by hand.
.blueprint-lifecycle.json
Why it exists: it records the Blueprint lifecycle checkpoint and the ownership facts that upgrade and remove rely on.
What it contains: the schema version; the Blueprint release whose lifecycle the repository has completed; completed upgrade operation ids; a pending upgrade, when one is in progress; and, per adopted application, the files Blueprint generated or created, the managed sections it owns, the exact shared-file edits it made, the folders it created, and the dependencies it installed.
Ownership: Blueprint owns it. Commit it and never edit it by hand. It is operational state, not architecture: blueprint.config.mjs stays the only architecture authority.
Lifecycle: init creates it on first adoption and adds ownership facts on every run. An adoption that has not finished — it failed part-way, deferred a required install with --no-install, or handed off to an authoring playbook — keeps the records for what it wrote, without claiming a completed lifecycle; the init run that completes adoption establishes the checkpoint. upgrade records a pending upgrade before changing anything and moves the checkpoint only after verification, and only while the file still records that pending upgrade. remove deletes it with the last adopted application. A repository adopted before lifecycle state existed gets a checkpoint from provable facts only; edits Blueprint made before that are reported by remove rather than reversed. If the file is unreadable, holds a path that leaves the repository, or is missing after it once entered Git history while the installed release always records it, every command that depends on it stops until it is restored from version control; so does a missing file whose Git history cannot be read. Blueprint never rebuilds it from the installed package. A missing file that no commit reachable from any ref ever contained is not treated as lost, because the history Git can still show does not prove a lifecycle existed, so that repository is treated as adopted before lifecycle state. Git cannot tell a dependency update from a lifecycle-aware adoption that never committed the file and then deleted it, so commit it so a later loss has history to restore from.
Writes: every command replaces the file atomically. It writes the complete new state to .blueprint-lifecycle.json.tmp first and renames that over the file, so an interrupted write leaves the previous state intact. A leftover .tmp file is never read as lifecycle state; the next write replaces it, and remove deletes it.
ESLint configuration
Why it exists: it carries executable module/layer flow, canonical alias, unit-entry, relative escape, package/global ownership, selfOnly, and optional rule gates.
What it contains: emitLint(blueprint, plugins) plus the embedded Blueprint plugin and required third-party plugin adapters.
Ownership and lifecycle depend on the project:
- No ESLint config
- Result:
eslint.config.mjsis created. - Ownership: Blueprint-owned while its generated first-line banner remains. A later
initmay regenerate it.
- Result:
- Blueprint generated the existing config
- Result: That same file is refreshed.
- Ownership: Blueprint-owned.
- A hand-authored flat config already exists
- Result:
eslint.config.blueprint.mjsis created and Blueprint prints merge instructions. - Ownership: Reference only; the adopter decides how to combine it with house rules, then removes the reference.
- Result:
- The existing flat config already wires
emitLint- Result: No config file is replaced.
- Ownership: Adopter-owned.
- Legacy
.eslintrcexists- Result: A flat reference config and migration instructions are produced.
- Ownership: The adopter owns the migration.
For a selected application below a repository-level flat config, that ancestor remains the live policy. init never writes a nested live config that would shadow it. If an earlier Blueprint run left such a generated shadow, init removes that generated file and emits a repository-root-ready reference instead; a hand-authored nested config is never removed. The reference imports the application blueprint by its repository path and computes an absolute applicationRoot for emitLint(..., { basePath: applicationRoot }). Its parser and anti-bypass entries use the same native flat-config basePath, so both Blueprint rules and existing repository rules reach the selected application whether ESLint is invoked from the repository or application directory.
Flat-config entries replace matching rule keys rather than merging their options. After manual integration, use blueprint doctor to check that the structural restrictions survive the final ordering.
Generated handbooks and Agent contracts distinguish a reference-only lint export from verified project-lint integration. A config mentioning Blueprint is not proof that its rules execute. After merging the export, rerun init: it checks effective rule survival and the safely replayable project lint command before upgrading the generated enforcement statement. Without that evidence, the documents explicitly retain an unverified or reference-only statement.
Architecture handbook
Default path: docs/architecture-handbook.md
Configured by: emit.handbook
Why it exists: it explains the architecture to people: topology, dependency diagram, layer responsibilities, naming, principles, component axes, rules, and playbook. A module-first handbook also states whether the application is still an empty runway and carries the module growth protocol for future product requirements.
Ownership: Blueprint owns the whole file at the resolved path and overwrites it on refresh. Edit the config authority, not the generated handbook.
Lifecycle: written on every scaffold/repair path with a valid config. If .gitignore hides it, init adds a narrow unignore entry so a generated contract cannot disappear from version control.
Agent contracts
emit.agents selects targets and may override each project-relative path. Omission defaults to Claude and AGENTS; an empty array emits none.
claude— Default path:CLAUDE.md; merge-managed shared document.agents— Default path:AGENTS.md; merge-managed shared document.gemini— Default path:GEMINI.md; merge-managed shared document.copilot— Default path:.github/copilot-instructions.md; merge-managed shared document.cursor— Default path:.cursor/rules/blueprint.mdc; Blueprint-owned rule file.windsurf— Default path:.windsurf/rules/blueprint.md; Blueprint-owned rule file.
Why they exist: they put architecture facts and non-mechanical project rules in the coding Agent's normal context.
What they contain: the resolved source layout, dependency and ownership boundaries, naming, configured doctrine, and verification commands. For module-first, they point new product boundaries at the module growth protocol instead of forbidding growth; inner layers, rules, and thresholds remain the owner's decision. Cursor and Windsurf add the frontmatter their tools require.
Merge-managed files: Blueprint owns only the text between <!-- BLUEPRINT:START --> and <!-- BLUEPRINT:END -->. Content outside the markers remains adopter-owned. If an existing shared file has no markers, Blueprint does not overwrite it:
- when the file already references
@kekkai/blueprint,initasks the adopter to add the managed markers around the existing integration; - otherwise it writes a sibling reference such as
CLAUDE.blueprint.mdorAGENTS.blueprint.mdand prints explicit merge instructions.
Reference files are temporary integration aids, not a second permanent contract.
Blueprint-owned files: Cursor and Windsurf rule files are replaced in full on refresh. If an output is removed from emit.agents, init may remove a wholly Blueprint-owned or wholly generated stale file. A shared hand-edited document is not deleted; Blueprint reports the stale marked section for the adopter to resolve.
As with the handbook, init adds narrow .gitignore exceptions when selected contract files would otherwise be hidden.
Fresh layer folders
A fresh layer-first preset may create missing layer directories under the resolved sourceRoot and place .gitkeep inside them. This gives an empty project the selected preset shape.
Existing source trees are never padded with absent layers, and module-first never invents module folders. A module-first runway starts with none; modules are materialized later through the module growth protocol when product work evidences them, and existing source requires authoring judgment.
Temporary workflow artifacts
blueprint-authoring.md
This root-level playbook is created for brownfield authoring (including module-first adoption of existing source), a forced --authoring run, and layer-first ↔ module-first transformation. It contains measured repository evidence, decision boundaries, steps, refusal conditions, and acceptance gates for the human or Agent completing the work.
Blueprint owns it only for the active workflow. It is not the architecture authority and must be removed after the playbook reaches its final cleanup step. doctor treats a leftover copy as incomplete adoption.
For repository-wide transformations, one playbook is written at the repository root and carries a separate measured section for every adopted application. Blueprint never moves application source automatically; the Agent follows the playbook and uses Git-aware moves.
blueprint-transformation.json
Layer-first → module-first work also creates this application-local, machine-consumed obligation. It records the recoverable Git head, application and source scope, framework/router position, and the measured pages, app, and containers source members. The Agent records every reviewed source → destination decision in target.decisions; replacing the config with a valid module-first config does not erase that obligation. Before writing the playbook, Blueprint retains the immutable origin in an application-scoped Git ref under refs/blueprint/transformations/. Deleting the JSON file or changing its origin blocks ordinary init until the recorded evidence is restored. These refs belong to this Git repository; ordinary clones do not transfer them automatically. Repository-wide registration commits all application refs in one atomic Git transaction; a failed registration leaves every application unregistered and can be retried after resolving Git access.
If initial artifact writing fails, or the editable JSON is later deleted, run blueprint init --recover-transformation in the affected application. Recovery validates the retained schema, original HEAD and application scope, restores missing JSON and a minimal recovery guide, and preserves existing valid JSON and decisions byte-for-byte. It does not scaffold, change source, launch an Agent or retire the obligation. Restored JSON contains the initial decisions: edits lost through deletion must be reviewed again. --dry-run previews without writing; other init options cannot be combined with recovery. A changed HEAD or unsafe retained scope blocks recovery. Each application can recover its own evidence after a repository-wide artifact-write failure.
Each decision includes source, destinations, and members: [{ source, destination }]. Every destinations contains exactly the members destination file paths, never module or unit directories. For example, use ["src/app/Game.tsx"], not ["src/app"]. Every origin member must map exactly once to a globally unique destination. Blueprint compares its Git origin content with the destination, requiring the same source extension and permitting CRLF normalization and module-specifier rewrites in ESM imports/exports, literal dynamic imports, unshadowed CommonJS require() and TypeScript import-equals only. Locally shadowed require calls and runtime expressions must remain unchanged. Other content edits require completing this verifiable move first; file existence or an unrelated existing module is not transfer evidence.
The next init --topology module-first verifies the recorded Git inventory, reserved app route composition, consumption of container seeds, destination positions, current import analysis, and all architecture error findings without baseline suppression. A conflicting requested topology is rejected until retirement. Only a successful verification retires this file and the transformation playbook. --authoring is explicitly re-authoring and never historical transformation proof. Hand-authored module-first projects without a pending Git transformation authority may intentionally use custom layer names such as pages or containers; Doctor and Inspect prove their current config, not a past migration.
.claude/commands/blueprint-author.md
This launcher contains the short Claude prompt that opens blueprint-authoring.md. It is created only when the resolved authoring policy includes Claude. Explicit --agent codex authoring does not create it; --agent claude does. A repository-wide transformation refuses conflicting application policies rather than choosing one launcher behavior.
The launcher is temporary and is removed with the authoring playbook after completion. doctor also treats a leftover launcher as incomplete adoption.
blueprint-upgrade.md
upgrade writes this root-level playbook when the resolved plan still contains semantic operations for a person or coding Agent. It lists only the effective operations for the whole source → target interval, in order, with the applications each applies to, what Blueprint measured, the instruction, how Blueprint verifies it, and whether it is already done. Canceled and superseded operations never appear.
It is regenerated from the pending upgrade on every run and deleted when the upgrade completes. It is not the lifecycle record: completion is recorded only in .blueprint-lifecycle.json, one operation at a time with blueprint upgrade --complete <operation-id>.
Reference and migration handoffs
Files matching *.blueprint.*, especially eslint.config.blueprint.mjs and merge-reference Agent documents, exist to support a manual integration decision. They should be removed when their contents have been incorporated. They are not regenerated product authorities, and doctor reports them while adoption remains unfinished. For legacy ESLint, retain eslint.config.blueprint.mjs until the owner chooses and completes flat-config migration. Doctor identifies that intended reference without asking for premature deletion; the separate unwired ESLint check remains incomplete.
Existing project files init may update
tsconfig.json, referenced TypeScript configs, or jsconfig.json
Blueprint ensures the canonical architecture.alias and any additionalAliases have compilerOptions.paths mappings to their configured roots.
- A parseable existing config is patched without replacing unrelated fields.
- A TypeScript references shell is followed to the application config when that target is available.
- A JavaScript project with no config may receive a minimal
jsconfig.json. - If a TypeScript config cannot be patched safely, Blueprint prints the exact manual wiring instead of inventing a new TypeScript configuration.
These files remain adopter-owned. For supported JSON edits, existing bytes outside the inserted alias properties are preserved, including compact arrays, indentation, and line endings. Blueprint only adds missing alias entries and leaves existing entries intact.
Bundler alias configuration
For a fresh Vite scaffold, Blueprint can add the canonical alias to the detected Vite config when the edit is structurally safe. Existing wiring through a quoted alias or a tsconfig-paths bridge is preserved. Otherwise init prints the required Vite or general bundler mapping for the adopter to apply.
The bundler configuration is adopter-owned. A TypeScript path mapping alone does not prove runtime module resolution, so doctor checks for toolchain wiring and the playbook also asks for a real build.
package.json and the package-manager lockfile
On a fresh scaffold, init may add a normal lint script or append an ESLint leg to an existing non-ESLint lint script when the edit is unambiguous. On an authored project it prints instructions instead of rewriting a house script it cannot safely interpret.
Unless --no-install is set, init runs the detected npm, pnpm, or Yarn command for missing Blueprint/ESLint dependencies. That package manager owns updates to package.json and its lockfile; Blueprint does not hand-edit lockfile syntax. In a workspace, detection follows the applicable package/toolchain root rather than assuming the current directory owns the lockfile.
.gitignore
If the configured handbook or selected Agent contracts are hidden by an existing ignore rule, init appends a marked group of narrow !path exceptions. It preserves the file's existing line ending style and does not broadly unignore its parent tree.
The adopter continues to own every other ignore rule.
.blueprint-baseline.json and eslint-suppressions.json
init does not create the inspection baseline. blueprint inspect --update-baseline owns creation or refresh of .blueprint-baseline.json, and inspect --baseline consumes it as accepted existing debt.
eslint-suppressions.json is also not generated by init; doctor only verifies that entries do not point at files that no longer exist. It checks both the application directory and the effective ESLint config directory, resolving each entry relative to its own ledger.
Verify the result
After integration or authoring completes:
npx @kekkai/blueprint inspect --baseline
npx @kekkai/blueprint doctor --jsonInspect the JSON result rather than the exit code alone when skipped Doctor checks must fail your automation. Run the project's normal lint and build as separate proof that the merged ESLint and alias configuration work in the real toolchain.
