// hosts/gemini/config-scaffold.ts — Scaffold .gemini/ config directory (SPEC-591)
// Writes .gemini/conventions.md, .gemini/skills/planu-*.md, and .gemini/hooks/
// equivalents when init_project runs inside a Gemini workspace.
// NOTE: This function deliberately does NOT create .claude/ files.
import { writeFile, readFile, mkdir, access } from 'node:fs/promises';
import { join } from 'node:path';
import { buildRulesForHost } from '../../engine/host-rules-templates/index.js';
import { assertEnglishOnlyArtifactText } from '../../engine/spec-language/english-only.js';
// ---------------------------------------------------------------------------
// File content generators
// ---------------------------------------------------------------------------
function buildConventionsMd() {
    return ([
        '# Planu Conventions for Gemini CLI',
        '',
        'Auto-generated by `init_project`. Update as conventions evolve.',
        '',
        '## Spec Driven Development',
        '',
        '- Every feature starts with a spec: `init_project` → `create_spec` → implement → `validate`',
        '- spec.md and technical.md are always in English',
        '- Acceptance criteria follow GIVEN/WHEN/THEN format',
        '',
        '## Tool Usage',
        '',
        '- Use `list_specs` to see current specs and their status',
        '- Use `update_status` to transition specs through the workflow',
        '- Use `validate` after implementation to check spec compliance',
        '',
        '## Multimodal Workflows',
        '',
        '- Attach an image or PDF to a `create_spec` request to trigger the',
        '  visual component context pipeline automatically',
        '- Figma design tokens are extracted automatically when present',
        '',
        '## Graceful Degradation',
        '',
        'The following Claude Code surfaces have no Gemini equivalent and fall back',
        'to single-agent inline execution:',
        '',
        '- Agent Teams → sequential inline tool calls',
        '- Plan mode → direct tool execution',
        '- Subagents → inline execution',
        '- Worktrees → not applicable',
    ].join('\n') + '\n');
}
function buildPlanuWorkflowSkillMd() {
    return ([
        '# Planu SDD Workflow (Gemini CLI)',
        '',
        'Core Spec Driven Development workflow for Planu inside Gemini CLI.',
        '',
        '## Trigger',
        'Use this when you want to create, implement, or validate a feature spec.',
        '',
        '## Steps',
        '',
        '1. `init_project` — initialize Planu for this project (once)',
        '2. `create_spec` — create a spec for the feature',
        '3. Review and approve the spec',
        '4. Implement the feature',
        '5. `validate` — verify spec compliance',
        '6. `update_status` with `done` — mark spec complete',
        '',
        '## Notes',
        '',
        '- Gemini CLI: attach images or PDFs to `create_spec` for visual workflows',
        '- Use `list_specs` to see current specs',
    ].join('\n') + '\n');
}
function buildPlanuMultimodalSkillMd() {
    return ([
        '# Planu Multimodal Spec (Gemini CLI)',
        '',
        'Create specs from images, PDFs, or Figma exports using Gemini native multimodal.',
        '',
        '## Trigger',
        'Use when you have an image, screenshot, or design file to turn into a spec.',
        '',
        '## Steps',
        '',
        '1. Attach the image/PDF/Figma export to your message',
        '2. Say "create a spec from this design"',
        '3. Planu automatically chains:',
        '   - `inject_component_context` — extracts visual component hints',
        '   - Figma token extraction (if tokens file detected)',
        '   - `create_spec` — creates the spec with visual context',
        '',
        '## Supported inputs',
        '',
        '- PNG, JPEG, WebP, SVG screenshots',
        '- PDF design documents',
        '- Figma export JSON (design tokens / variables)',
    ].join('\n') + '\n');
}
function buildPreToolHookSh() {
    return ([
        '#!/bin/sh',
        '# .gemini/hooks/pre-tool.sh — Gemini equivalent of Claude Code PreToolUse hook',
        '# Called by Gemini CLI before each tool invocation (if hooks are supported).',
        '# Planu uses this as a no-op placeholder — extend as needed.',
        'exit 0',
    ].join('\n') + '\n');
}
function buildPostToolHookSh() {
    return ([
        '#!/bin/sh',
        '# .gemini/hooks/post-tool.sh — Gemini equivalent of Claude Code PostToolUse hook',
        '# Called by Gemini CLI after each tool invocation (if hooks are supported).',
        '# Planu uses this as a no-op placeholder — extend as needed.',
        'exit 0',
    ].join('\n') + '\n');
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Scaffold the .gemini/ config directory with Planu conventions and skills.
 * Idempotent — skips files that already exist.
 * SPEC-708: also injects a host-aware Planu rules block into .gemini/conventions.md.
 * The body of conventions.md is never overwritten; only the rules block between
 * `<!-- planu:rules:start -->` markers is replaced on subsequent runs.
 * Does NOT create any .claude/ files.
 *
 * Called by init_project when a Gemini workspace is detected.
 * Integration hook for handler.ts: see REPORT at end of implementation.
 */
export async function scaffoldGeminiConfig(projectPath, planuVersion = '1.96.0') {
    const filesCreated = [];
    const filesSkipped = [];
    const filesToWrite = [
        { relPath: '.gemini/conventions.md', content: buildConventionsMd() },
        { relPath: '.gemini/skills/planu-workflow.md', content: buildPlanuWorkflowSkillMd() },
        { relPath: '.gemini/skills/planu-multimodal.md', content: buildPlanuMultimodalSkillMd() },
        { relPath: '.gemini/hooks/pre-tool.sh', content: buildPreToolHookSh() },
        { relPath: '.gemini/hooks/post-tool.sh', content: buildPostToolHookSh() },
    ];
    for (const { relPath, content } of filesToWrite) {
        const fullPath = join(projectPath, relPath);
        const existed = await fileExists(fullPath);
        if (existed) {
            filesSkipped.push(relPath);
        }
        else {
            // Ensure parent directory exists
            const parentDir = join(projectPath, relPath.split('/').slice(0, -1).join('/'));
            await mkdir(parentDir, { recursive: true });
            const artifactKind = relPath.includes('/skills/') ? 'skill' : 'agent';
            assertEnglishOnlyArtifactText(content, artifactKind);
            await writeFile(fullPath, content, 'utf-8');
            filesCreated.push(relPath);
        }
    }
    // SPEC-708: idempotent rules block injection (always runs, even if conventions.md existed)
    await injectRulesBlock(join(projectPath, '.gemini/conventions.md'), planuVersion);
    return {
        modified: filesCreated.length > 0,
        filesCreated,
        filesSkipped,
        claudeFilesOmitted: true, // this function never creates .claude/ files — by design
    };
}
const PLANU_RULES_BLOCK_REGEX = /<!-- planu:rules:start[\s\S]*?<!-- planu:rules:end -->/;
const PLANU_RULES_START_REGEX = /<!-- planu:rules:start[^>]* -->/;
/**
 * SPEC-708: idempotently inject the Planu rules block into a Gemini conventions file.
 * Uses host='gemini' so the questions rule references Gemini's native interactive prompt
 * instead of `AskUserQuestion`.
 */
async function injectRulesBlock(filePath, version) {
    const block = buildRulesForHost('gemini', version).rules;
    assertEnglishOnlyArtifactText(block, 'rule');
    let existing;
    try {
        existing = await readFile(filePath, 'utf-8');
    }
    catch {
        return;
    }
    const updated = PLANU_RULES_START_REGEX.test(existing)
        ? existing.replace(PLANU_RULES_BLOCK_REGEX, block)
        : `${existing.trimEnd()}\n\n${block}\n`;
    if (updated !== existing) {
        await writeFile(filePath, updated, 'utf-8');
    }
}
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
async function fileExists(filePath) {
    try {
        await access(filePath);
        return true;
    }
    catch {
        return false;
    }
}
//# sourceMappingURL=config-scaffold.js.map