/** * CAAMP injection management — manages agent instruction file injection. * * Extracted from init.ts to enable shared use across init, upgrade, and doctor. * * Handles: * 1. Injecting @AGENTS.md into provider instruction files (CLAUDE.md, GEMINI.md, etc.) * 2. Injecting CLEO protocol content into AGENTS.md itself * 3. Installing CLEO-INJECTION.md to global templates directory * 4. Creating global ~/.agents/AGENTS.md hub * 5. Stripping legacy CLEO blocks and removing deprecated files * 6. Checking injection health (CAAMP markers, @ reference resolution) * * @task T4682 */ import type { Provider } from '@cleocode/caamp'; import type { UpgradeFileJournal } from './scaffold/upgrade-file-journal.js'; import { type GlobalInstructionRefreshReport } from '@cleocode/contracts/caamp-markers'; import type { ScaffoldResult } from '@cleocode/contracts/scaffold-diagnostics'; export type { ScaffoldResult } from '@cleocode/contracts/scaffold-diagnostics'; /** Structural alias of {@link CheckResult} used by injection health checks. */ export interface InjectionCheckResult { id: string; category: string; status: 'passed' | 'failed' | 'warning' | 'info'; message: string; details: Record; fix: string | null; } /** * Get the CLEO-INJECTION.md template content from the package templates/ directory. * Returns null if the template file is not found. */ export declare function getInjectionTemplateContent(): string | null; /** * File name of the on-demand protocol reference shipped beside * `CLEO-INJECTION.md` in the package `templates/` directory. * * `CLEO-INJECTION.md` is the always-loaded core that every session and * tier-1 spawn prompt carries. Reference sections (task creation, sagas, * nexus, orchestration, docs, evidence detail, …) live in this file, which is * never `@`-referenced — agents print one section on demand with * `cleo briefing inject --section `, and tier-2 spawn prompts embed it. * * @task T12580 */ export declare const CLEO_REFERENCE_TEMPLATE = "CLEO-REFERENCE.md"; /** * Extract a named section delimited by * `` … ``. * * @param content - Template text (core or reference). * @param sectionName - Section anchor name. * @returns The trimmed content between the anchors, or null when absent. */ export declare function extractInjectionSection(content: string, sectionName: string): string | null; /** * List every section anchor name declared in a template, in document order. * * @param content - Template text (core or reference). * @returns Section names; duplicates are dropped. */ export declare function listInjectionSections(content: string): string[]; /** Result of {@link readInjectionSection}. */ export interface InjectionSectionLookup { /** Requested section name. */ section: string; /** Section body, or null when no source declares it. */ content: string | null; /** Absolute path of the file the section came from, or null when not found. */ source: string | null; /** Every section name the searched sources declare (core first). */ available: string[]; } /** * Resolve one protocol section across the always-loaded core and the * on-demand reference. * * Sources, in order: the package-bundled `CLEO-INJECTION.md` and * {@link CLEO_REFERENCE_TEMPLATE} (version-matched with the running CLI), then * the installed `/templates/CLEO-INJECTION.md` as a fallback for a * layout whose package templates are missing. * * @param sectionName - Section anchor name, e.g. `task-creation`. * @param templatesDir - Package templates directory; defaults to the bundled one. * @returns The section content with its source, plus every available name. * @task T12580 */ export declare function readInjectionSection(sectionName: string, templatesDir?: string): InjectionSectionLookup; /** * Strip hardcoded `...` blocks * from AGENTS.md. These blocks are replaced by the `@.cleo/nexus-bridge.md` * reference which contains auto-generated code intelligence content (T552). * * Also strips any other known vendor marker blocks using the same pattern * (e.g. `...`). * * @param filePath - Absolute path to the file to strip * @returns True if the file was modified, false otherwise */ export declare function stripGitNexusBlocks(filePath: string): Promise; /** * Full injection refresh: strip legacy blocks, inject CAAMP content, * install global template, create hub. * * Replaces initInjection from init.ts with a ScaffoldResult return type. * * Target architecture: * CLAUDE.md/GEMINI.md -> @AGENTS.md (via injectAll) * AGENTS.md -> @~/.agents/AGENTS.md + @.cleo/project-context.json + @.cleo/memory-bridge.md + @.cleo/nexus-bridge.md * * In `upgrade` mode (T13409) the files the project owns are refreshed only * inside an existing CAAMP block (references in a git-tracked file, embedded * otherwise; `injection.delivery` overrides), a file without markers is left alone, an * absent provider file is not created, the existing `~/.agents/AGENTS.md` hub is * never rewritten, and every changed file is backed up through `options.journal`. * * @param projectRoot - Absolute project root. * @param options - Mode and backup journal. * @returns What was refreshed, created or skipped. * * @task T4682 * @task T13409 */ export declare function ensureInjection(projectRoot: string, options?: EnsureInjectionOptions): Promise; /** Options for {@link ensureInjection}. */ export interface EnsureInjectionOptions { /** * `init` writes every provider file and the hub; `upgrade` refreshes only * existing CLEO-managed blocks and backs up what it changes (T13409). * @defaultValue 'init' */ mode?: 'init' | 'upgrade'; /** Journal receiving backups of the files an upgrade changes. */ journal?: UpgradeFileJournal; } /** * Build a smart, contextual contributor block for AGENTS.md injection. * Returns null if this is not a contributor project. * * The block is INFORMATIONAL, not prescriptive. It tells agents: * - This is the CLEO source repo (contributor project) * - cleo-dev is available (or not, with reason) * - Prefer cleo-dev for unreleased features, but fall back to cleo if * the dev build is broken or unavailable * * This avoids the trap where a hardcoded "ALWAYS use cleo-dev" instruction * sends agents into a loop when the dev build has compile errors. */ export declare function buildContributorInjectionBlock(projectRoot: string): string | null; /** * Verify injection health: AGENTS.md exists, has CAAMP markers, * markers are balanced, and @ references resolve. * * Combines logic from doctor/checks.ts checkAgentsMdHub, * checkCaampMarkerIntegrity, and checkAtReferenceTargetExists. */ export declare function checkInjection(projectRoot: string): InjectionCheckResult; /** * Exact command that regenerates every global provider instruction file. It is * the owner's to run: CLEO never writes those files itself (T13409). */ export declare const GLOBAL_INSTRUCTION_REMEDY = "caamp instructions update --global"; /** Exact command that restores a missing or dead `caamp` binary. */ export declare const CAAMP_BINARY_REMEDY = "npm install -g @cleocode/caamp"; /** * Options for {@link refreshStaleGlobalInstructions}. */ export interface RefreshStaleGlobalInstructionsOptions { /** Wall-clock bound in milliseconds. @defaultValue 2000 */ timeoutMs?: number; /** Providers to scan and refresh. @defaultValue every installed provider */ providers?: Provider[]; /** Run even under Vitest (tests pass a temp HOME and explicit providers). @defaultValue false */ force?: boolean; } /** * Report global provider instruction files whose stamped source changed since * delivery — the automatic check behind `cleo session start` and `cleo briefing`. * * @remarks * This runs the cheap scan (`checkGlobalInstructionStaleness` — one read per * provider file, one hash per stamped source, no reference expansion). Until * T13409 it then regenerated the stale files, which rewrote the owner's * `~/.claude/CLAUDE.md`; CLEO never writes user-global instruction files, so a * stale file is now reported as `skipped` with {@link GLOBAL_INSTRUCTION_REMEDY}. * * It is bounded (`timeoutMs`), never throws, and writes nothing to stdout: the * outcome is returned for the caller to place in its envelope. Set * `CLEO_INSTRUCTION_AUTOREFRESH=0` to disable it. Under Vitest it is skipped * unless `force` is set, so a test can never rewrite the real provider files. * * @param options - Bound, targets and test override. * @returns What was found and what was refreshed. * * @example * ```typescript * const report = await refreshStaleGlobalInstructions(); * if (report.status === 'failed') process.stderr.write(`${report.remedy}\n`); * ``` * * @task T12378 * @task T13409 */ export declare function refreshStaleGlobalInstructions(options?: RefreshStaleGlobalInstructionsOptions): Promise; /** * Doctor check: are the global provider instruction files current, and does * any carry a hand-appended copy of managed content? * * @remarks * Read-only — it runs the cheap staleness scan and never writes. * * @returns One result for delivery freshness and one for duplicates. * * @task T12378 */ export declare function checkGlobalInstructionDelivery(): Promise; /** * Doctor check: is a working `caamp` binary on PATH? * * @remarks * A dangling `caamp` symlink (left behind when the package it pointed into was * removed or moved) makes every `caamp …` remedy fail with a confusing * "No such file or directory". Reports the first working binary, else the dead * links found, else that none exists — each with the exact remedy. * * @param pathEnv - PATH to search. @defaultValue `process.env.PATH` * @returns The check result. * * @example * ```typescript * const check = checkCaampBinary(); * if (check.fix) process.stderr.write(`${check.fix}\n`); * ``` * * @task T12378 */ export declare function checkCaampBinary(pathEnv?: string): InjectionCheckResult; //# sourceMappingURL=injection.d.ts.map