Merge pull request 'feat: complete bootstrap → monorepo migration (archive-ready)' (#345) from feat/framework-migration-complete into main
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed

This commit was merged in pull request #345.
This commit is contained in:
2026-04-02 02:24:33 +00:00
51 changed files with 9410 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ export default tseslint.config(
'**/coverage/**', '**/coverage/**',
'**/drizzle.config.ts', '**/drizzle.config.ts',
'**/framework/**', '**/framework/**',
'packages/mosaic/__tests__/**',
], ],
}, },
{ {

View File

@@ -0,0 +1,109 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import {
mkdtempSync,
mkdirSync,
writeFileSync,
readFileSync,
existsSync,
rmSync,
cpSync,
} from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { HeadlessPrompter } from '../../src/prompter/headless-prompter.js';
import { createConfigService } from '../../src/config/config-service.js';
import { runWizard } from '../../src/wizard.js';
describe('Full Wizard (headless)', () => {
let tmpDir: string;
const repoRoot = join(import.meta.dirname, '..', '..');
beforeEach(() => {
tmpDir = mkdtempSync(join(tmpdir(), 'mosaic-wizard-test-'));
// Copy templates to tmp dir
const templatesDir = join(repoRoot, 'templates');
if (existsSync(templatesDir)) {
cpSync(templatesDir, join(tmpDir, 'templates'), { recursive: true });
}
});
afterEach(() => {
rmSync(tmpDir, { recursive: true, force: true });
});
it('quick start produces valid SOUL.md', async () => {
const prompter = new HeadlessPrompter({
'Installation mode': 'quick',
'What name should agents use?': 'TestBot',
'Communication style': 'direct',
'Your name': 'Tester',
'Your pronouns': 'They/Them',
'Your timezone': 'UTC',
});
await runWizard({
mosaicHome: tmpDir,
sourceDir: tmpDir,
prompter,
configService: createConfigService(tmpDir, tmpDir),
});
const soulPath = join(tmpDir, 'SOUL.md');
expect(existsSync(soulPath)).toBe(true);
const soul = readFileSync(soulPath, 'utf-8');
expect(soul).toContain('You are **TestBot**');
expect(soul).toContain('Be direct, concise, and concrete');
expect(soul).toContain('execution partner and visibility engine');
});
it('quick start produces valid USER.md', async () => {
const prompter = new HeadlessPrompter({
'Installation mode': 'quick',
'What name should agents use?': 'TestBot',
'Communication style': 'direct',
'Your name': 'Tester',
'Your pronouns': 'He/Him',
'Your timezone': 'America/Chicago',
});
await runWizard({
mosaicHome: tmpDir,
sourceDir: tmpDir,
prompter,
configService: createConfigService(tmpDir, tmpDir),
});
const userPath = join(tmpDir, 'USER.md');
expect(existsSync(userPath)).toBe(true);
const user = readFileSync(userPath, 'utf-8');
expect(user).toContain('**Name:** Tester');
expect(user).toContain('**Pronouns:** He/Him');
expect(user).toContain('**Timezone:** America/Chicago');
});
it('applies CLI overrides', async () => {
const prompter = new HeadlessPrompter({
'Installation mode': 'quick',
'Your name': 'FromPrompt',
});
await runWizard({
mosaicHome: tmpDir,
sourceDir: tmpDir,
prompter,
configService: createConfigService(tmpDir, tmpDir),
cliOverrides: {
soul: {
agentName: 'FromCLI',
communicationStyle: 'formal',
},
},
});
const soul = readFileSync(join(tmpDir, 'SOUL.md'), 'utf-8');
expect(soul).toContain('You are **FromCLI**');
expect(soul).toContain('Use professional, structured language');
});
});

View File

@@ -0,0 +1,68 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { HeadlessPrompter } from '../../src/prompter/headless-prompter.js';
import { detectInstallStage } from '../../src/stages/detect-install.js';
import type { WizardState } from '../../src/types.js';
import type { ConfigService } from '../../src/config/config-service.js';
function createState(mosaicHome: string): WizardState {
return {
mosaicHome,
sourceDir: mosaicHome,
mode: 'quick',
installAction: 'fresh',
soul: {},
user: {},
tools: {},
runtimes: { detected: [], mcpConfigured: false },
selectedSkills: [],
};
}
const mockConfig: ConfigService = {
readSoul: async () => ({ agentName: 'TestAgent' }),
readUser: async () => ({ userName: 'TestUser' }),
readTools: async () => ({}),
writeSoul: async () => {},
writeUser: async () => {},
writeTools: async () => {},
syncFramework: async () => {},
};
describe('detectInstallStage', () => {
let tmpDir: string;
beforeEach(() => {
tmpDir = mkdtempSync(join(tmpdir(), 'mosaic-test-'));
});
afterEach(() => {
rmSync(tmpDir, { recursive: true, force: true });
});
it('sets fresh for empty directory', async () => {
const p = new HeadlessPrompter({});
const state = createState(join(tmpDir, 'nonexistent'));
await detectInstallStage(p, state, mockConfig);
expect(state.installAction).toBe('fresh');
});
it('detects existing install and offers choices', async () => {
// Create a mock existing install
mkdirSync(join(tmpDir, 'bin'), { recursive: true });
writeFileSync(join(tmpDir, 'AGENTS.md'), '# Test');
writeFileSync(join(tmpDir, 'SOUL.md'), 'You are **Jarvis** in this session.');
const p = new HeadlessPrompter({
'What would you like to do?': 'keep',
});
const state = createState(tmpDir);
await detectInstallStage(p, state, mockConfig);
expect(state.installAction).toBe('keep');
expect(state.soul.agentName).toBe('TestAgent');
});
});

View File

@@ -0,0 +1,72 @@
import { describe, it, expect } from 'vitest';
import { HeadlessPrompter } from '../../src/prompter/headless-prompter.js';
import { soulSetupStage } from '../../src/stages/soul-setup.js';
import type { WizardState } from '../../src/types.js';
function createState(overrides: Partial<WizardState> = {}): WizardState {
return {
mosaicHome: '/tmp/test-mosaic',
sourceDir: '/tmp/test-mosaic',
mode: 'quick',
installAction: 'fresh',
soul: {},
user: {},
tools: {},
runtimes: { detected: [], mcpConfigured: false },
selectedSkills: [],
...overrides,
};
}
describe('soulSetupStage', () => {
it('sets agent name and style in quick mode', async () => {
const p = new HeadlessPrompter({
'What name should agents use?': 'Jarvis',
'Communication style': 'friendly',
});
const state = createState({ mode: 'quick' });
await soulSetupStage(p, state);
expect(state.soul.agentName).toBe('Jarvis');
expect(state.soul.communicationStyle).toBe('friendly');
expect(state.soul.roleDescription).toBe('execution partner and visibility engine');
});
it('uses defaults in quick mode with no answers', async () => {
const p = new HeadlessPrompter({});
const state = createState({ mode: 'quick' });
await soulSetupStage(p, state);
expect(state.soul.agentName).toBe('Assistant');
expect(state.soul.communicationStyle).toBe('direct');
});
it('skips when install action is keep', async () => {
const p = new HeadlessPrompter({});
const state = createState({ installAction: 'keep' });
state.soul.agentName = 'Existing';
await soulSetupStage(p, state);
expect(state.soul.agentName).toBe('Existing');
});
it('asks for all fields in advanced mode', async () => {
const p = new HeadlessPrompter({
'What name should agents use?': 'Atlas',
'Agent role description': 'memory keeper',
'Communication style': 'formal',
'Accessibility preferences': 'ADHD-friendly',
'Custom guardrails (optional)': 'Never push to main',
});
const state = createState({ mode: 'advanced' });
await soulSetupStage(p, state);
expect(state.soul.agentName).toBe('Atlas');
expect(state.soul.roleDescription).toBe('memory keeper');
expect(state.soul.communicationStyle).toBe('formal');
expect(state.soul.accessibility).toBe('ADHD-friendly');
expect(state.soul.customGuardrails).toBe('Never push to main');
});
});

View File

@@ -0,0 +1,60 @@
import { describe, it, expect } from 'vitest';
import { HeadlessPrompter } from '../../src/prompter/headless-prompter.js';
import { userSetupStage } from '../../src/stages/user-setup.js';
import type { WizardState } from '../../src/types.js';
function createState(overrides: Partial<WizardState> = {}): WizardState {
return {
mosaicHome: '/tmp/test-mosaic',
sourceDir: '/tmp/test-mosaic',
mode: 'quick',
installAction: 'fresh',
soul: { communicationStyle: 'direct' },
user: {},
tools: {},
runtimes: { detected: [], mcpConfigured: false },
selectedSkills: [],
...overrides,
};
}
describe('userSetupStage', () => {
it('collects basic info in quick mode', async () => {
const p = new HeadlessPrompter({
'Your name': 'Jason',
'Your pronouns': 'He/Him',
'Your timezone': 'America/Chicago',
});
const state = createState({ mode: 'quick' });
await userSetupStage(p, state);
expect(state.user.userName).toBe('Jason');
expect(state.user.pronouns).toBe('He/Him');
expect(state.user.timezone).toBe('America/Chicago');
expect(state.user.communicationPrefs).toContain('Direct and concise');
});
it('skips when install action is keep', async () => {
const p = new HeadlessPrompter({});
const state = createState({ installAction: 'keep' });
state.user.userName = 'Existing';
await userSetupStage(p, state);
expect(state.user.userName).toBe('Existing');
});
it('derives communication prefs from soul style', async () => {
const p = new HeadlessPrompter({
'Your name': 'Test',
});
const state = createState({
mode: 'quick',
soul: { communicationStyle: 'friendly' },
});
await userSetupStage(p, state);
expect(state.user.communicationPrefs).toContain('Warm and conversational');
});
});

View File

@@ -0,0 +1,97 @@
import { describe, it, expect } from 'vitest';
import {
buildSoulTemplateVars,
buildUserTemplateVars,
buildToolsTemplateVars,
} from '../../src/template/builders.js';
describe('buildSoulTemplateVars', () => {
it('builds direct style correctly', () => {
const vars = buildSoulTemplateVars({
agentName: 'Jarvis',
communicationStyle: 'direct',
});
expect(vars.AGENT_NAME).toBe('Jarvis');
expect(vars.BEHAVIORAL_PRINCIPLES).toContain('Clarity over performance theater');
expect(vars.COMMUNICATION_STYLE).toContain('Be direct, concise, and concrete');
});
it('builds friendly style correctly', () => {
const vars = buildSoulTemplateVars({
communicationStyle: 'friendly',
});
expect(vars.BEHAVIORAL_PRINCIPLES).toContain('Be helpful and approachable');
expect(vars.COMMUNICATION_STYLE).toContain('Be warm and conversational');
});
it('builds formal style correctly', () => {
const vars = buildSoulTemplateVars({
communicationStyle: 'formal',
});
expect(vars.BEHAVIORAL_PRINCIPLES).toContain('Maintain professional, structured');
expect(vars.COMMUNICATION_STYLE).toContain('Use professional, structured language');
});
it('appends accessibility to principles', () => {
const vars = buildSoulTemplateVars({
communicationStyle: 'direct',
accessibility: 'ADHD-friendly chunking',
});
expect(vars.BEHAVIORAL_PRINCIPLES).toContain('6. ADHD-friendly chunking.');
});
it('does not append accessibility when "none"', () => {
const vars = buildSoulTemplateVars({
communicationStyle: 'direct',
accessibility: 'none',
});
expect(vars.BEHAVIORAL_PRINCIPLES).not.toContain('6.');
});
it('formats custom guardrails', () => {
const vars = buildSoulTemplateVars({
customGuardrails: 'Never auto-commit',
});
expect(vars.CUSTOM_GUARDRAILS).toBe('- Never auto-commit');
});
it('uses defaults when config is empty', () => {
const vars = buildSoulTemplateVars({});
expect(vars.AGENT_NAME).toBe('Assistant');
expect(vars.ROLE_DESCRIPTION).toBe('execution partner and visibility engine');
});
});
describe('buildUserTemplateVars', () => {
it('maps all fields', () => {
const vars = buildUserTemplateVars({
userName: 'Jason',
pronouns: 'He/Him',
timezone: 'America/Chicago',
});
expect(vars.USER_NAME).toBe('Jason');
expect(vars.PRONOUNS).toBe('He/Him');
expect(vars.TIMEZONE).toBe('America/Chicago');
});
it('uses defaults for missing fields', () => {
const vars = buildUserTemplateVars({});
expect(vars.PRONOUNS).toBe('They/Them');
expect(vars.TIMEZONE).toBe('UTC');
});
});
describe('buildToolsTemplateVars', () => {
it('builds git providers table', () => {
const vars = buildToolsTemplateVars({
gitProviders: [{ name: 'GitHub', url: 'https://github.com', cli: 'gh', purpose: 'OSS' }],
});
expect(vars.GIT_PROVIDERS_TABLE).toContain('| GitHub |');
expect(vars.GIT_PROVIDERS_TABLE).toContain('`gh`');
});
it('uses default table when no providers', () => {
const vars = buildToolsTemplateVars({});
expect(vars.GIT_PROVIDERS_TABLE).toContain('add your git providers here');
});
});

View File

@@ -0,0 +1,52 @@
import { describe, it, expect } from 'vitest';
import { renderTemplate } from '../../src/template/engine.js';
describe('renderTemplate', () => {
it('replaces all placeholders', () => {
const template = 'You are **{{AGENT_NAME}}**, role: {{ROLE_DESCRIPTION}}';
const result = renderTemplate(template, {
AGENT_NAME: 'Jarvis',
ROLE_DESCRIPTION: 'steward',
});
expect(result).toBe('You are **Jarvis**, role: steward');
});
it('preserves ${ENV_VAR} references', () => {
const template = 'Path: ${HOME}/.config, Agent: {{AGENT_NAME}}';
const result = renderTemplate(template, { AGENT_NAME: 'Test' });
expect(result).toBe('Path: ${HOME}/.config, Agent: Test');
});
it('handles multi-line values', () => {
const template = '{{PRINCIPLES}}';
const result = renderTemplate(template, {
PRINCIPLES: '1. First\n2. Second\n3. Third',
});
expect(result).toBe('1. First\n2. Second\n3. Third');
});
it('replaces unset vars with empty string by default', () => {
const template = 'Before {{MISSING}} After';
const result = renderTemplate(template, {});
expect(result).toBe('Before After');
});
it('throws in strict mode for missing vars', () => {
const template = '{{MISSING}}';
expect(() => renderTemplate(template, {}, { strict: true })).toThrow(
'Template variable not provided: {{MISSING}}',
);
});
it('handles multiple occurrences of same placeholder', () => {
const template = '{{NAME}} says hello, {{NAME}}!';
const result = renderTemplate(template, { NAME: 'Jarvis' });
expect(result).toBe('Jarvis says hello, Jarvis!');
});
it('preserves non-placeholder curly braces', () => {
const template = 'const x = { foo: {{VALUE}} }';
const result = renderTemplate(template, { VALUE: '"bar"' });
expect(result).toBe('const x = { foo: "bar" }');
});
});

View File

@@ -0,0 +1,17 @@
# Claude Adapter
Use this adapter when running Claude CLI sessions.
## Required Context
1. `~/.config/mosaic/STANDARDS.md`
2. `<repo>/AGENTS.md`
## Command Wrapper
Use wrapper commands from `~/.config/mosaic/bin/` for lifecycle rituals.
## Migration Note
Project-local `.claude/commands/*.md` should call `scripts/agent/*.sh` so behavior stays runtime-neutral.
Guides and tools should resolve to `~/.config/mosaic/guides` and `~/.config/mosaic/tools` (linked into `~/.claude` for compatibility).

View File

@@ -0,0 +1,13 @@
# Codex Adapter
Use this adapter when running Codex CLI sessions.
## Required Context
1. `~/.config/mosaic/STANDARDS.md`
2. `<repo>/AGENTS.md`
## Runtime Behavior
- Favor repo lifecycle scripts under `scripts/agent/` for start/end rituals.
- Keep instructions and quality gates aligned with Mosaic standards.

View File

@@ -0,0 +1,14 @@
# Generic Adapter
For runtimes without a first-class adapter yet.
## Required Context
1. Load `~/.config/mosaic/STANDARDS.md`
2. Load project `AGENTS.md`
## Minimal Contract
- Use `scripts/agent/session-start.sh` at start if present.
- Use `scripts/agent/session-end.sh` before completion if present.
- If missing, run equivalent repo commands and report what was executed.

View File

@@ -0,0 +1,36 @@
# Pi Adapter
Use this adapter when running Pi sessions via `mosaic pi`.
## Required Context
1. `~/.config/mosaic/STANDARDS.md`
2. `<repo>/AGENTS.md`
## Integration
Pi is the native Mosaic agent runtime. The `mosaic pi` launcher:
1. Injects the full runtime contract via `--append-system-prompt`
2. Loads Mosaic skills via `--skill` flags
3. Loads the Mosaic extension via `--extension` for lifecycle hooks
4. Detects active missions and injects initial prompts
## Capabilities vs Other Runtimes
- No permission restrictions (no yolo flag needed)
- Native thinking levels replace sequential-thinking MCP
- Native skill discovery compatible with Mosaic SKILL.md format
- Native extension system for lifecycle hooks (TypeScript, not bash shims)
- Native session persistence and resume
- Model-agnostic (Anthropic, OpenAI, Google, Ollama, custom providers)
## Command Wrapper
```bash
mosaic pi # Interactive session
mosaic pi "Fix the auth bug" # With initial prompt
mosaic yolo pi # Identical to mosaic pi
mosaic coord --pi run # Coordinator-driven session
mosaic prdy --pi init # PRD creation via Pi
```

View File

@@ -0,0 +1,283 @@
# mosaic-doctor.ps1
# Audits Mosaic runtime state and detects drift across agent runtimes.
# PowerShell equivalent of mosaic-doctor (bash).
$ErrorActionPreference = "Stop"
param(
[switch]$FailOnWarn,
[switch]$Verbose,
[switch]$Help
)
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
if ($Help) {
Write-Host @"
Usage: mosaic-doctor.ps1 [-FailOnWarn] [-Verbose] [-Help]
Audit Mosaic runtime state and detect drift across agent runtimes.
"@
exit 0
}
$script:warnCount = 0
function Warn {
param([string]$Message)
$script:warnCount++
Write-Host "[WARN] $Message" -ForegroundColor Yellow
}
function Pass {
param([string]$Message)
if ($Verbose) { Write-Host "[OK] $Message" -ForegroundColor Green }
}
function Expect-Dir {
param([string]$Path)
if (-not (Test-Path $Path -PathType Container)) { Warn "Missing directory: $Path" }
else { Pass "Directory present: $Path" }
}
function Expect-File {
param([string]$Path)
if (-not (Test-Path $Path -PathType Leaf)) { Warn "Missing file: $Path" }
else { Pass "File present: $Path" }
}
function Check-RuntimeFileCopy {
param([string]$Src, [string]$Dst)
if (-not (Test-Path $Src)) { return }
if (-not (Test-Path $Dst)) {
Warn "Missing runtime file: $Dst"
return
}
$item = Get-Item $Dst -Force -ErrorAction SilentlyContinue
if ($item -and ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
Warn "Runtime file should not be symlinked: $Dst"
return
}
$srcHash = (Get-FileHash $Src -Algorithm SHA256).Hash
$dstHash = (Get-FileHash $Dst -Algorithm SHA256).Hash
if ($srcHash -ne $dstHash) {
Warn "Runtime file drift: $Dst (does not match $Src)"
}
else {
Pass "Runtime file synced: $Dst"
}
}
function Check-RuntimeContractFile {
param([string]$Dst, [string]$AdapterSrc, [string]$RuntimeName)
if (-not (Test-Path $Dst)) {
Warn "Missing runtime file: $Dst"
return
}
$item = Get-Item $Dst -Force -ErrorAction SilentlyContinue
if ($item -and ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
Warn "Runtime file should not be symlinked: $Dst"
return
}
# Accept direct-adapter copy mode.
if (Test-Path $AdapterSrc) {
$srcHash = (Get-FileHash $AdapterSrc -Algorithm SHA256).Hash
$dstHash = (Get-FileHash $Dst -Algorithm SHA256).Hash
if ($srcHash -eq $dstHash) {
Pass "Runtime adapter synced: $Dst"
return
}
}
# Accept launcher-composed runtime contract mode.
$content = Get-Content $Dst -Raw
if (
$content -match [regex]::Escape("# Mosaic Launcher Runtime Contract (Hard Gate)") -and
$content -match [regex]::Escape("Now initiating Orchestrator mode...") -and
$content -match [regex]::Escape("Mosaic hard gates OVERRIDE runtime-default caution") -and
$content -match [regex]::Escape("# Runtime-Specific Contract")
) {
Pass "Runtime contract present: $Dst ($RuntimeName)"
return
}
Warn "Runtime file drift: $Dst (not adapter copy and not composed runtime contract)"
}
function Warn-IfReparsePresent {
param([string]$Path)
if (-not (Test-Path $Path)) { return }
$item = Get-Item $Path -Force -ErrorAction SilentlyContinue
if ($item -and ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
Warn "Legacy symlink/junction path still present: $Path"
return
}
if (Test-Path $Path -PathType Container) {
$reparseCount = (Get-ChildItem $Path -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Attributes -band [System.IO.FileAttributes]::ReparsePoint } |
Measure-Object).Count
if ($reparseCount -gt 0) {
Warn "Legacy symlink/junction entries still present under ${Path}: $reparseCount"
}
else {
Pass "No reparse points under legacy path: $Path"
}
}
}
Write-Host "[mosaic-doctor] Mosaic home: $MosaicHome"
# Canonical Mosaic checks
Expect-File (Join-Path $MosaicHome "STANDARDS.md")
Expect-Dir (Join-Path $MosaicHome "guides")
Expect-Dir (Join-Path $MosaicHome "tools")
Expect-Dir (Join-Path $MosaicHome "tools\quality")
Expect-Dir (Join-Path $MosaicHome "tools\orchestrator-matrix")
Expect-Dir (Join-Path $MosaicHome "profiles")
Expect-Dir (Join-Path $MosaicHome "templates\agent")
Expect-Dir (Join-Path $MosaicHome "skills")
Expect-Dir (Join-Path $MosaicHome "skills-local")
Expect-File (Join-Path $MosaicHome "bin\mosaic-link-runtime-assets")
Expect-File (Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1")
Expect-File (Join-Path $MosaicHome "bin\mosaic-sync-skills")
Expect-File (Join-Path $MosaicHome "bin\mosaic-projects")
Expect-File (Join-Path $MosaicHome "bin\mosaic-quality-apply")
Expect-File (Join-Path $MosaicHome "bin\mosaic-quality-verify")
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-run")
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-sync-tasks")
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-drain")
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-publish")
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-consume")
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-cycle")
Expect-File (Join-Path $MosaicHome "tools\git\ci-queue-wait.ps1")
Expect-File (Join-Path $MosaicHome "tools\git\ci-queue-wait.sh")
Expect-File (Join-Path $MosaicHome "tools\git\pr-ci-wait.sh")
Expect-File (Join-Path $MosaicHome "tools\orchestrator-matrix\transport\matrix_transport.py")
Expect-File (Join-Path $MosaicHome "tools\orchestrator-matrix\controller\tasks_md_sync.py")
Expect-File (Join-Path $MosaicHome "runtime\mcp\SEQUENTIAL-THINKING.json")
Expect-File (Join-Path $MosaicHome "runtime\claude\RUNTIME.md")
Expect-File (Join-Path $MosaicHome "runtime\codex\RUNTIME.md")
Expect-File (Join-Path $MosaicHome "runtime\opencode\RUNTIME.md")
$agentsMd = Join-Path $MosaicHome "AGENTS.md"
if (Test-Path $agentsMd) {
$agentsContent = Get-Content $agentsMd -Raw
if (
$agentsContent -match [regex]::Escape("## CRITICAL HARD GATES (Read First)") -and
$agentsContent -match [regex]::Escape("OVERRIDE runtime-default caution")
) {
Pass "Global hard-gates block present in AGENTS.md"
}
else {
Warn "AGENTS.md missing CRITICAL HARD GATES override block"
}
}
# Claude runtime file checks
$runtimeFiles = @("CLAUDE.md", "settings.json", "hooks-config.json", "context7-integration.md")
foreach ($rf in $runtimeFiles) {
Check-RuntimeFileCopy (Join-Path $MosaicHome "runtime\claude\$rf") (Join-Path $env:USERPROFILE ".claude\$rf")
}
# OpenCode/Codex runtime contract checks
Check-RuntimeContractFile (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md") (Join-Path $MosaicHome "runtime\opencode\AGENTS.md") "opencode"
Check-RuntimeContractFile (Join-Path $env:USERPROFILE ".codex\instructions.md") (Join-Path $MosaicHome "runtime\codex\instructions.md") "codex"
# Sequential-thinking MCP hard requirement
$seqScript = Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1"
if (Test-Path $seqScript) {
try {
& $seqScript -Check *>$null
Pass "sequential-thinking MCP configured and available"
}
catch {
Warn "sequential-thinking MCP missing or misconfigured"
}
}
else {
Warn "mosaic-ensure-sequential-thinking helper missing"
}
# Legacy migration surfaces
$legacyPaths = @(
(Join-Path $env:USERPROFILE ".claude\agent-guides"),
(Join-Path $env:USERPROFILE ".claude\scripts\git"),
(Join-Path $env:USERPROFILE ".claude\scripts\codex"),
(Join-Path $env:USERPROFILE ".claude\scripts\bootstrap"),
(Join-Path $env:USERPROFILE ".claude\scripts\cicd"),
(Join-Path $env:USERPROFILE ".claude\scripts\portainer"),
(Join-Path $env:USERPROFILE ".claude\templates"),
(Join-Path $env:USERPROFILE ".claude\presets\domains"),
(Join-Path $env:USERPROFILE ".claude\presets\tech-stacks"),
(Join-Path $env:USERPROFILE ".claude\presets\workflows")
)
foreach ($p in $legacyPaths) {
Warn-IfReparsePresent $p
}
# Skills runtime checks (junctions or symlinks into runtime-specific dirs)
$linkTargets = @(
(Join-Path $env:USERPROFILE ".claude\skills"),
(Join-Path $env:USERPROFILE ".codex\skills"),
(Join-Path $env:USERPROFILE ".config\opencode\skills")
)
$skillSources = @($MosaicHome + "\skills", $MosaicHome + "\skills-local")
foreach ($runtimeSkills in $linkTargets) {
if (-not (Test-Path $runtimeSkills)) { continue }
foreach ($sourceDir in $skillSources) {
if (-not (Test-Path $sourceDir)) { continue }
Get-ChildItem $sourceDir -Directory | Where-Object { -not $_.Name.StartsWith(".") } | ForEach-Object {
$name = $_.Name
$skillPath = $_.FullName
$target = Join-Path $runtimeSkills $name
if (-not (Test-Path $target)) {
Warn "Missing skill link: $target"
return
}
$item = Get-Item $target -Force -ErrorAction SilentlyContinue
if (-not ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
Warn "Non-junction skill entry: $target"
return
}
$targetResolved = $item.Target
if (-not $targetResolved -or (Resolve-Path $targetResolved -ErrorAction SilentlyContinue).Path -ne (Resolve-Path $skillPath -ErrorAction SilentlyContinue).Path) {
Warn "Drifted skill link: $target (expected -> $skillPath)"
}
else {
Pass "Linked skill: $target"
}
}
}
}
# Broken junctions/symlinks in managed runtime skill dirs
$brokenLinks = 0
foreach ($d in $linkTargets) {
if (-not (Test-Path $d)) { continue }
Get-ChildItem $d -Force -ErrorAction SilentlyContinue | Where-Object {
($_.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -and -not (Test-Path $_.FullName)
} | ForEach-Object { $brokenLinks++ }
}
if ($brokenLinks -gt 0) {
Warn "Broken skill junctions/symlinks detected: $brokenLinks"
}
Write-Host "[mosaic-doctor] warnings=$($script:warnCount)"
if ($FailOnWarn -and $script:warnCount -gt 0) {
exit 1
}

View File

@@ -0,0 +1,114 @@
# mosaic-ensure-sequential-thinking.ps1
param(
[switch]$Check
)
$ErrorActionPreference = "Stop"
$Pkg = "@modelcontextprotocol/server-sequential-thinking"
function Require-Binary {
param([string]$Name)
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
throw "Required binary missing: $Name"
}
}
function Warm-Package {
$null = & npx -y $Pkg --help 2>$null
}
function Set-ClaudeConfig {
$path = Join-Path $env:USERPROFILE ".claude\settings.json"
New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null
$data = @{}
if (Test-Path $path) {
try { $data = Get-Content $path -Raw | ConvertFrom-Json -AsHashtable } catch { $data = @{} }
}
if (-not $data.ContainsKey("mcpServers") -or -not ($data["mcpServers"] -is [hashtable])) {
$data["mcpServers"] = @{}
}
$data["mcpServers"]["sequential-thinking"] = @{
command = "npx"
args = @("-y", "@modelcontextprotocol/server-sequential-thinking")
}
$data | ConvertTo-Json -Depth 20 | Set-Content -Path $path -Encoding UTF8
}
function Set-CodexConfig {
$path = Join-Path $env:USERPROFILE ".codex\config.toml"
New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null
if (-not (Test-Path $path)) { New-Item -ItemType File -Path $path -Force | Out-Null }
$content = Get-Content $path -Raw
$content = [regex]::Replace($content, "(?ms)^\[mcp_servers\.(sequential-thinking|sequential_thinking)\].*?(?=^\[|\z)", "")
$content = $content.TrimEnd() + "`n`n[mcp_servers.sequential-thinking]`ncommand = `"npx`"`nargs = [`"-y`", `"@modelcontextprotocol/server-sequential-thinking`"]`n"
Set-Content -Path $path -Value $content -Encoding UTF8
}
function Set-OpenCodeConfig {
$path = Join-Path $env:USERPROFILE ".config\opencode\config.json"
New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null
$data = @{}
if (Test-Path $path) {
try { $data = Get-Content $path -Raw | ConvertFrom-Json -AsHashtable } catch { $data = @{} }
}
if (-not $data.ContainsKey("mcp") -or -not ($data["mcp"] -is [hashtable])) {
$data["mcp"] = @{}
}
$data["mcp"]["sequential-thinking"] = @{
type = "local"
command = @("npx", "-y", "@modelcontextprotocol/server-sequential-thinking")
enabled = $true
}
$data | ConvertTo-Json -Depth 20 | Set-Content -Path $path -Encoding UTF8
}
function Test-Configs {
$claudeOk = $false
$codexOk = $false
$opencodeOk = $false
$claudePath = Join-Path $env:USERPROFILE ".claude\settings.json"
if (Test-Path $claudePath) {
try {
$c = Get-Content $claudePath -Raw | ConvertFrom-Json -AsHashtable
$claudeOk = $c.ContainsKey("mcpServers") -and $c["mcpServers"].ContainsKey("sequential-thinking")
} catch {}
}
$codexPath = Join-Path $env:USERPROFILE ".codex\config.toml"
if (Test-Path $codexPath) {
$raw = Get-Content $codexPath -Raw
$codexOk = $raw -match "\[mcp_servers\.(sequential-thinking|sequential_thinking)\]" -and $raw -match "@modelcontextprotocol/server-sequential-thinking"
}
$opencodePath = Join-Path $env:USERPROFILE ".config\opencode\config.json"
if (Test-Path $opencodePath) {
try {
$o = Get-Content $opencodePath -Raw | ConvertFrom-Json -AsHashtable
$opencodeOk = $o.ContainsKey("mcp") -and $o["mcp"].ContainsKey("sequential-thinking")
} catch {}
}
if (-not ($claudeOk -and $codexOk -and $opencodeOk)) {
throw "Sequential-thinking MCP runtime config is incomplete"
}
}
Require-Binary node
Require-Binary npx
Warm-Package
if ($Check) {
Test-Configs
Write-Host "[mosaic-seq] sequential-thinking MCP is configured and available"
exit 0
}
Set-ClaudeConfig
Set-CodexConfig
Set-OpenCodeConfig
Write-Host "[mosaic-seq] sequential-thinking MCP configured for Claude, Codex, and OpenCode"

View File

@@ -0,0 +1,144 @@
# mosaic-init.ps1 — Interactive SOUL.md generator (Windows)
#
# Usage:
# mosaic-init.ps1 # Interactive mode
# mosaic-init.ps1 -Name "Jarvis" -Style direct # Flag overrides
$ErrorActionPreference = "Stop"
param(
[string]$Name,
[string]$Role,
[ValidateSet("direct", "friendly", "formal")]
[string]$Style,
[string]$Accessibility,
[string]$Guardrails,
[switch]$NonInteractive,
[switch]$Help
)
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$Template = Join-Path $MosaicHome "templates\SOUL.md.template"
$Output = Join-Path $MosaicHome "SOUL.md"
if ($Help) {
Write-Host @"
Usage: mosaic-init.ps1 [-Name <name>] [-Role <desc>] [-Style direct|friendly|formal]
[-Accessibility <prefs>] [-Guardrails <rules>] [-NonInteractive]
Generate ~/.config/mosaic/SOUL.md - the universal agent identity contract.
Interactive by default. Use flags to skip prompts.
"@
exit 0
}
function Prompt-IfEmpty {
param([string]$Current, [string]$PromptText, [string]$Default = "")
if ($Current) { return $Current }
if ($NonInteractive) {
if ($Default) { return $Default }
Write-Host "[mosaic-init] ERROR: Value required in non-interactive mode: $PromptText" -ForegroundColor Red
exit 1
}
$display = if ($Default) { "$PromptText [$Default]" } else { $PromptText }
$value = Read-Host $display
if (-not $value -and $Default) { return $Default }
return $value
}
Write-Host "[mosaic-init] Generating SOUL.md - your universal agent identity contract"
Write-Host ""
$Name = Prompt-IfEmpty $Name "What name should agents use" "Assistant"
$Role = Prompt-IfEmpty $Role "Agent role description" "execution partner and visibility engine"
if (-not $Style) {
if ($NonInteractive) {
$Style = "direct"
}
else {
Write-Host ""
Write-Host "Communication style:"
Write-Host " 1) direct - Concise, no fluff, actionable"
Write-Host " 2) friendly - Warm but efficient, conversational"
Write-Host " 3) formal - Professional, structured, thorough"
$choice = Read-Host "Choose [1/2/3] (default: 1)"
$Style = switch ($choice) {
"2" { "friendly" }
"3" { "formal" }
default { "direct" }
}
}
}
$Accessibility = Prompt-IfEmpty $Accessibility "Accessibility preferences (or 'none')" "none"
if (-not $Guardrails -and -not $NonInteractive) {
Write-Host ""
$Guardrails = Read-Host "Custom guardrails (optional, press Enter to skip)"
}
# Build behavioral principles
$BehavioralPrinciples = switch ($Style) {
"direct" {
"1. Clarity over performance theater.`n2. Practical execution over abstract planning.`n3. Truthfulness over confidence: state uncertainty explicitly.`n4. Visible state over hidden assumptions."
}
"friendly" {
"1. Be helpful and approachable while staying efficient.`n2. Provide context and explain reasoning when helpful.`n3. Truthfulness over confidence: state uncertainty explicitly.`n4. Visible state over hidden assumptions."
}
"formal" {
"1. Maintain professional, structured communication.`n2. Provide thorough analysis with explicit tradeoffs.`n3. Truthfulness over confidence: state uncertainty explicitly.`n4. Document decisions and rationale clearly."
}
}
if ($Accessibility -and $Accessibility -ne "none") {
$BehavioralPrinciples += "`n5. $Accessibility."
}
# Build communication style
$CommunicationStyle = switch ($Style) {
"direct" {
"- Be direct, concise, and concrete.`n- Avoid fluff, hype, and anthropomorphic roleplay.`n- Do not simulate certainty when facts are missing.`n- Prefer actionable next steps and explicit tradeoffs."
}
"friendly" {
"- Be warm and conversational while staying focused.`n- Explain your reasoning when it helps the user.`n- Do not simulate certainty when facts are missing.`n- Prefer actionable next steps with clear context."
}
"formal" {
"- Use professional, structured language.`n- Provide thorough explanations with supporting detail.`n- Do not simulate certainty when facts are missing.`n- Present options with explicit tradeoffs and recommendations."
}
}
# Format custom guardrails
$FormattedGuardrails = if ($Guardrails) { "- $Guardrails" } else { "" }
# Verify template
if (-not (Test-Path $Template)) {
Write-Host "[mosaic-init] ERROR: Template not found: $Template" -ForegroundColor Red
exit 1
}
# Generate SOUL.md
$content = Get-Content $Template -Raw
$content = $content -replace '\{\{AGENT_NAME\}\}', $Name
$content = $content -replace '\{\{ROLE_DESCRIPTION\}\}', $Role
$content = $content -replace '\{\{BEHAVIORAL_PRINCIPLES\}\}', $BehavioralPrinciples
$content = $content -replace '\{\{COMMUNICATION_STYLE\}\}', $CommunicationStyle
$content = $content -replace '\{\{CUSTOM_GUARDRAILS\}\}', $FormattedGuardrails
Set-Content -Path $Output -Value $content -Encoding UTF8
Write-Host ""
Write-Host "[mosaic-init] Generated: $Output"
Write-Host "[mosaic-init] Agent name: $Name"
Write-Host "[mosaic-init] Style: $Style"
# Push to runtime adapters
$linkScript = Join-Path $MosaicHome "bin\mosaic-link-runtime-assets.ps1"
if (Test-Path $linkScript) {
Write-Host "[mosaic-init] Updating runtime adapters..."
& $linkScript
}
Write-Host "[mosaic-init] Done. Launch with: mosaic claude"

View File

@@ -0,0 +1,111 @@
# mosaic-link-runtime-assets.ps1
# Syncs Mosaic runtime config files into agent runtime directories.
# PowerShell equivalent of mosaic-link-runtime-assets (bash).
$ErrorActionPreference = "Stop"
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$BackupStamp = Get-Date -Format "yyyyMMddHHmmss"
function Copy-FileManaged {
param([string]$Src, [string]$Dst)
$parent = Split-Path $Dst -Parent
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
# Remove existing symlink/junction
$item = Get-Item $Dst -Force -ErrorAction SilentlyContinue
if ($item -and $item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) {
Remove-Item $Dst -Force
}
if (Test-Path $Dst) {
$srcHash = (Get-FileHash $Src -Algorithm SHA256).Hash
$dstHash = (Get-FileHash $Dst -Algorithm SHA256).Hash
if ($srcHash -eq $dstHash) { return }
Rename-Item $Dst "$Dst.mosaic-bak-$BackupStamp"
}
Copy-Item $Src $Dst -Force
}
function Remove-LegacyPath {
param([string]$Path)
if (-not (Test-Path $Path)) { return }
$item = Get-Item $Path -Force -ErrorAction SilentlyContinue
if ($item -and $item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) {
Remove-Item $Path -Force
return
}
if (Test-Path $Path -PathType Container) {
# Remove symlinks/junctions inside, then empty dirs
Get-ChildItem $Path -Recurse -Force | Where-Object {
$_.Attributes -band [System.IO.FileAttributes]::ReparsePoint
} | Remove-Item -Force
Get-ChildItem $Path -Recurse -Directory -Force |
Sort-Object { $_.FullName.Length } -Descending |
Where-Object { (Get-ChildItem $_.FullName -Force | Measure-Object).Count -eq 0 } |
Remove-Item -Force
}
}
# Remove legacy compatibility paths
$legacyPaths = @(
(Join-Path $env:USERPROFILE ".claude\agent-guides"),
(Join-Path $env:USERPROFILE ".claude\scripts\git"),
(Join-Path $env:USERPROFILE ".claude\scripts\codex"),
(Join-Path $env:USERPROFILE ".claude\scripts\bootstrap"),
(Join-Path $env:USERPROFILE ".claude\scripts\cicd"),
(Join-Path $env:USERPROFILE ".claude\scripts\portainer"),
(Join-Path $env:USERPROFILE ".claude\scripts\debug-hook.sh"),
(Join-Path $env:USERPROFILE ".claude\scripts\qa-hook-handler.sh"),
(Join-Path $env:USERPROFILE ".claude\scripts\qa-hook-stdin.sh"),
(Join-Path $env:USERPROFILE ".claude\scripts\qa-hook-wrapper.sh"),
(Join-Path $env:USERPROFILE ".claude\scripts\qa-queue-monitor.sh"),
(Join-Path $env:USERPROFILE ".claude\scripts\remediation-hook-handler.sh"),
(Join-Path $env:USERPROFILE ".claude\templates"),
(Join-Path $env:USERPROFILE ".claude\presets\domains"),
(Join-Path $env:USERPROFILE ".claude\presets\tech-stacks"),
(Join-Path $env:USERPROFILE ".claude\presets\workflows"),
(Join-Path $env:USERPROFILE ".claude\presets\jarvis-loop.json")
)
foreach ($p in $legacyPaths) {
Remove-LegacyPath $p
}
# Claude-specific runtime files (settings, hooks — CLAUDE.md is now a thin pointer)
$runtimeFiles = @("CLAUDE.md", "settings.json", "hooks-config.json", "context7-integration.md")
foreach ($rf in $runtimeFiles) {
$src = Join-Path $MosaicHome "runtime\claude\$rf"
if (-not (Test-Path $src)) { continue }
$dst = Join-Path $env:USERPROFILE ".claude\$rf"
Copy-FileManaged $src $dst
}
# OpenCode runtime adapter
$opencodeSrc = Join-Path $MosaicHome "runtime\opencode\AGENTS.md"
if (Test-Path $opencodeSrc) {
$opencodeDst = Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md"
Copy-FileManaged $opencodeSrc $opencodeDst
}
# Codex runtime adapter
$codexSrc = Join-Path $MosaicHome "runtime\codex\instructions.md"
if (Test-Path $codexSrc) {
$codexDir = Join-Path $env:USERPROFILE ".codex"
if (-not (Test-Path $codexDir)) { New-Item -ItemType Directory -Path $codexDir -Force | Out-Null }
$codexDst = Join-Path $codexDir "instructions.md"
Copy-FileManaged $codexSrc $codexDst
}
$seqScript = Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1"
if (Test-Path $seqScript) {
& $seqScript
}
Write-Host "[mosaic-link] Runtime assets synced (non-symlink mode)"
Write-Host "[mosaic-link] Canonical source: $MosaicHome"

View File

@@ -0,0 +1,90 @@
# mosaic-migrate-local-skills.ps1
# Migrates runtime-local skill directories to Mosaic-managed junctions.
# Uses directory junctions (no elevation required) with fallback to copies.
# PowerShell equivalent of mosaic-migrate-local-skills (bash).
$ErrorActionPreference = "Stop"
param(
[switch]$Apply,
[switch]$Help
)
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$LocalSkillsDir = Join-Path $MosaicHome "skills-local"
if ($Help) {
Write-Host @"
Usage: mosaic-migrate-local-skills.ps1 [-Apply] [-Help]
Migrate runtime-local skill directories (e.g. ~/.claude/skills/jarvis) to
Mosaic-managed skills by replacing local directories with junctions to
~/.config/mosaic/skills-local.
Default mode is dry-run.
"@
exit 0
}
if (-not (Test-Path $LocalSkillsDir)) {
Write-Host "[mosaic-local-skills] Missing local skills dir: $LocalSkillsDir" -ForegroundColor Red
exit 1
}
$skillRoots = @(
(Join-Path $env:USERPROFILE ".claude\skills"),
(Join-Path $env:USERPROFILE ".codex\skills"),
(Join-Path $env:USERPROFILE ".config\opencode\skills")
)
$count = 0
Get-ChildItem $LocalSkillsDir -Directory | ForEach-Object {
$name = $_.Name
$src = $_.FullName
foreach ($root in $skillRoots) {
if (-not (Test-Path $root)) { continue }
$target = Join-Path $root $name
# Already a junction/symlink — check if it points to the right place
$existing = Get-Item $target -Force -ErrorAction SilentlyContinue
if ($existing -and ($existing.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
$currentTarget = $existing.Target
if ($currentTarget -and ($currentTarget -eq $src -or (Resolve-Path $currentTarget -ErrorAction SilentlyContinue).Path -eq (Resolve-Path $src -ErrorAction SilentlyContinue).Path)) {
continue
}
}
# Only migrate local directories containing SKILL.md
if ((Test-Path $target -PathType Container) -and
(Test-Path (Join-Path $target "SKILL.md")) -and
-not ($existing -and ($existing.Attributes -band [System.IO.FileAttributes]::ReparsePoint))) {
$count++
if ($Apply) {
$stamp = Get-Date -Format "yyyyMMddHHmmss"
Rename-Item $target "$target.mosaic-bak-$stamp"
try {
New-Item -ItemType Junction -Path $target -Target $src -ErrorAction Stop | Out-Null
Write-Host "[mosaic-local-skills] migrated: $target -> $src"
}
catch {
Write-Host "[mosaic-local-skills] Junction failed for $name, falling back to copy"
Copy-Item $src $target -Recurse -Force
Write-Host "[mosaic-local-skills] copied: $target <- $src"
}
}
else {
Write-Host "[mosaic-local-skills] would migrate: $target -> $src"
}
}
}
}
if ($Apply) {
Write-Host "[mosaic-local-skills] complete: migrated=$count"
}
else {
Write-Host "[mosaic-local-skills] dry-run: migratable=$count"
Write-Host "[mosaic-local-skills] re-run with -Apply to migrate"
}

View File

@@ -0,0 +1,65 @@
# mosaic-release-upgrade.ps1 — Upgrade installed Mosaic framework release (Windows)
#
# Usage:
# mosaic-release-upgrade.ps1
# mosaic-release-upgrade.ps1 -Ref main -Keep
# mosaic-release-upgrade.ps1 -Ref v0.2.0 -Overwrite -Yes
#
param(
[string]$Ref = $(if ($env:MOSAIC_BOOTSTRAP_REF) { $env:MOSAIC_BOOTSTRAP_REF } else { "main" }),
[switch]$Keep,
[switch]$Overwrite,
[switch]$Yes,
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$RemoteInstallerUrl = if ($env:MOSAIC_REMOTE_INSTALL_URL) {
$env:MOSAIC_REMOTE_INSTALL_URL
} else {
"https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.ps1"
}
$installMode = if ($Overwrite) { "overwrite" } elseif ($Keep) { "keep" } elseif ($env:MOSAIC_INSTALL_MODE) { $env:MOSAIC_INSTALL_MODE } else { "keep" }
if ($installMode -notin @("keep", "overwrite")) {
Write-Host "[mosaic-release-upgrade] Invalid install mode: $installMode" -ForegroundColor Red
exit 1
}
$currentVersion = "unknown"
$mosaicCmd = Join-Path $MosaicHome "bin\mosaic.ps1"
if (Test-Path $mosaicCmd) {
try {
$currentVersion = (& $mosaicCmd --version) -replace '^mosaic\s+', ''
}
catch {
$currentVersion = "unknown"
}
}
Write-Host "[mosaic-release-upgrade] Current version: $currentVersion"
Write-Host "[mosaic-release-upgrade] Target ref: $Ref"
Write-Host "[mosaic-release-upgrade] Install mode: $installMode"
Write-Host "[mosaic-release-upgrade] Installer URL: $RemoteInstallerUrl"
if ($DryRun) {
Write-Host "[mosaic-release-upgrade] Dry run: no changes applied."
exit 0
}
if (-not $Yes) {
$confirmation = Read-Host "Proceed with Mosaic release upgrade? [y/N]"
if ($confirmation -notin @("y", "Y", "yes", "YES")) {
Write-Host "[mosaic-release-upgrade] Aborted."
exit 1
}
}
$env:MOSAIC_BOOTSTRAP_REF = $Ref
$env:MOSAIC_INSTALL_MODE = $installMode
$env:MOSAIC_HOME = $MosaicHome
Invoke-RestMethod -Uri $RemoteInstallerUrl | Invoke-Expression

View File

@@ -0,0 +1,126 @@
# mosaic-sync-skills.ps1
# Syncs canonical skills and links them into agent runtime skill directories.
# Uses directory junctions (no elevation required) with fallback to copies.
# PowerShell equivalent of mosaic-sync-skills (bash).
$ErrorActionPreference = "Stop"
param(
[switch]$LinkOnly,
[switch]$NoLink,
[switch]$Help
)
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$SkillsRepoUrl = if ($env:MOSAIC_SKILLS_REPO_URL) { $env:MOSAIC_SKILLS_REPO_URL } else { "https://git.mosaicstack.dev/mosaic/agent-skills.git" }
$SkillsRepoDir = if ($env:MOSAIC_SKILLS_REPO_DIR) { $env:MOSAIC_SKILLS_REPO_DIR } else { Join-Path $MosaicHome "sources\agent-skills" }
$MosaicSkillsDir = Join-Path $MosaicHome "skills"
$MosaicLocalSkillsDir = Join-Path $MosaicHome "skills-local"
if ($Help) {
Write-Host @"
Usage: mosaic-sync-skills.ps1 [-LinkOnly] [-NoLink] [-Help]
Sync canonical skills into ~/.config/mosaic/skills and link all Mosaic skills
into runtime skill directories using directory junctions.
Options:
-LinkOnly Skip git clone/pull and only relink
-NoLink Sync canonical skills but do not update runtime links
-Help Show help
"@
exit 0
}
foreach ($d in @($MosaicHome, $MosaicSkillsDir, $MosaicLocalSkillsDir)) {
if (-not (Test-Path $d)) { New-Item -ItemType Directory -Path $d -Force | Out-Null }
}
# Fetch skills from git
if (-not $LinkOnly) {
if (Test-Path (Join-Path $SkillsRepoDir ".git")) {
Write-Host "[mosaic-skills] Updating skills source: $SkillsRepoDir"
git -C $SkillsRepoDir pull --rebase
}
else {
Write-Host "[mosaic-skills] Cloning skills source to: $SkillsRepoDir"
$parentDir = Split-Path $SkillsRepoDir -Parent
if (-not (Test-Path $parentDir)) { New-Item -ItemType Directory -Path $parentDir -Force | Out-Null }
git clone $SkillsRepoUrl $SkillsRepoDir
}
$sourceSkillsDir = Join-Path $SkillsRepoDir "skills"
if (-not (Test-Path $sourceSkillsDir)) {
Write-Host "[mosaic-skills] Missing source skills dir: $sourceSkillsDir" -ForegroundColor Red
exit 1
}
# Sync: remove old, copy new
if (Test-Path $MosaicSkillsDir) {
Get-ChildItem $MosaicSkillsDir | Remove-Item -Recurse -Force
}
Copy-Item "$sourceSkillsDir\*" $MosaicSkillsDir -Recurse -Force
}
if (-not (Test-Path $MosaicSkillsDir)) {
Write-Host "[mosaic-skills] Canonical skills dir missing: $MosaicSkillsDir" -ForegroundColor Red
exit 1
}
if ($NoLink) {
Write-Host "[mosaic-skills] Canonical sync completed (link update skipped)"
exit 0
}
function Link-SkillIntoTarget {
param([string]$SkillPath, [string]$TargetDir)
$name = Split-Path $SkillPath -Leaf
if ($name.StartsWith(".")) { return }
$linkPath = Join-Path $TargetDir $name
# Already a junction/symlink — recreate
$existing = Get-Item $linkPath -Force -ErrorAction SilentlyContinue
if ($existing -and ($existing.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
Remove-Item $linkPath -Force
}
elseif ($existing) {
Write-Host "[mosaic-skills] Preserve existing runtime-specific entry: $linkPath"
return
}
# Try junction first, fall back to copy
try {
New-Item -ItemType Junction -Path $linkPath -Target $SkillPath -ErrorAction Stop | Out-Null
}
catch {
Write-Host "[mosaic-skills] Junction failed for $name, falling back to copy"
Copy-Item $SkillPath $linkPath -Recurse -Force
}
}
$linkTargets = @(
(Join-Path $env:USERPROFILE ".claude\skills"),
(Join-Path $env:USERPROFILE ".codex\skills"),
(Join-Path $env:USERPROFILE ".config\opencode\skills")
)
foreach ($target in $linkTargets) {
if (-not (Test-Path $target)) { New-Item -ItemType Directory -Path $target -Force | Out-Null }
# Link canonical skills
Get-ChildItem $MosaicSkillsDir -Directory | ForEach-Object {
Link-SkillIntoTarget $_.FullName $target
}
# Link local skills
if (Test-Path $MosaicLocalSkillsDir) {
Get-ChildItem $MosaicLocalSkillsDir -Directory | ForEach-Object {
Link-SkillIntoTarget $_.FullName $target
}
}
Write-Host "[mosaic-skills] Linked skills into: $target"
}
Write-Host "[mosaic-skills] Complete"

View File

@@ -0,0 +1,437 @@
# mosaic.ps1 — Unified agent launcher and management CLI (Windows)
#
# AGENTS.md is the global policy source for all agent sessions.
# The launcher injects a composed runtime contract (AGENTS + runtime reference).
#
# Usage:
# mosaic claude [args...] Launch Claude Code with runtime contract injected
# mosaic opencode [args...] Launch OpenCode with runtime contract injected
# mosaic codex [args...] Launch Codex with runtime contract injected
# mosaic yolo <runtime> [args...] Launch runtime in dangerous-permissions mode
# mosaic --yolo <runtime> [args...] Alias for yolo
# mosaic init [args...] Generate SOUL.md interactively
# mosaic doctor [args...] Health audit
# mosaic sync [args...] Sync skills
$ErrorActionPreference = "Stop"
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$Version = "0.1.0"
function Show-Usage {
Write-Host @"
mosaic $Version - Unified agent launcher
Usage: mosaic <command> [args...]
Agent Launchers:
claude [args...] Launch Claude Code with runtime contract injected
opencode [args...] Launch OpenCode with runtime contract injected
codex [args...] Launch Codex with runtime contract injected
yolo <runtime> [args...] Dangerous mode for claude|codex|opencode
--yolo <runtime> [args...] Alias for yolo
Management:
init [args...] Generate SOUL.md (agent identity contract)
doctor [args...] Audit runtime state and detect drift
sync [args...] Sync skills from canonical source
bootstrap <path> Bootstrap a repo with Mosaic standards
upgrade [mode] [args] Upgrade release (default) or project files
upgrade check Check release upgrade status (no changes)
release-upgrade [...] Upgrade installed Mosaic release
project-upgrade [...] Clean up stale SOUL.md/CLAUDE.md in a project
Options:
-h, --help Show this help
-v, --version Show version
"@
}
function Assert-MosaicHome {
if (-not (Test-Path $MosaicHome)) {
Write-Host "[mosaic] ERROR: ~/.config/mosaic not found." -ForegroundColor Red
Write-Host "[mosaic] Install with: irm https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.ps1 | iex"
exit 1
}
}
function Assert-AgentsMd {
$agentsPath = Join-Path $MosaicHome "AGENTS.md"
if (-not (Test-Path $agentsPath)) {
Write-Host "[mosaic] ERROR: ~/.config/mosaic/AGENTS.md not found." -ForegroundColor Red
Write-Host "[mosaic] Re-run the installer."
exit 1
}
}
function Assert-Soul {
$soulPath = Join-Path $MosaicHome "SOUL.md"
if (-not (Test-Path $soulPath)) {
Write-Host "[mosaic] SOUL.md not found. Running mosaic init..."
& (Join-Path $MosaicHome "bin\mosaic-init.ps1")
}
}
function Assert-Runtime {
param([string]$Cmd)
if (-not (Get-Command $Cmd -ErrorAction SilentlyContinue)) {
Write-Host "[mosaic] ERROR: '$Cmd' not found in PATH." -ForegroundColor Red
Write-Host "[mosaic] Install $Cmd before launching."
exit 1
}
}
function Assert-SequentialThinking {
$checker = Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1"
if (-not (Test-Path $checker)) {
Write-Host "[mosaic] ERROR: sequential-thinking checker missing: $checker" -ForegroundColor Red
exit 1
}
try {
& $checker -Check *>$null
}
catch {
Write-Host "[mosaic] ERROR: sequential-thinking MCP is required but not configured." -ForegroundColor Red
Write-Host "[mosaic] Run: $checker"
exit 1
}
}
function Get-ActiveMission {
$missionFile = Join-Path (Get-Location) ".mosaic\orchestrator\mission.json"
if (-not (Test-Path $missionFile)) {
return $null
}
try {
$mission = Get-Content $missionFile -Raw | ConvertFrom-Json
}
catch {
return $null
}
$status = [string]$mission.status
if ([string]::IsNullOrWhiteSpace($status)) {
$status = "inactive"
}
if ($status -ne "active" -and $status -ne "paused") {
return $null
}
$name = [string]$mission.name
if ([string]::IsNullOrWhiteSpace($name)) {
$name = "unnamed"
}
$id = [string]$mission.mission_id
if ([string]::IsNullOrWhiteSpace($id)) {
$id = ""
}
$milestones = @($mission.milestones)
$milestoneCount = $milestones.Count
$milestoneCompleted = @($milestones | Where-Object { $_.status -eq "completed" }).Count
return [PSCustomObject]@{
Name = $name
Id = $id
Status = $status
MilestoneCount = $milestoneCount
MilestoneCompleted = $milestoneCompleted
}
}
function Get-MissionContractBlock {
$mission = Get-ActiveMission
if ($null -eq $mission) {
return ""
}
return @"
# ACTIVE MISSION HARD GATE (Read Before Anything Else)
An active orchestration mission exists in this project. This is a BLOCKING requirement.
**Mission:** $($mission.Name)
**ID:** $($mission.Id)
**Status:** $($mission.Status)
**Milestones:** $($mission.MilestoneCompleted) / $($mission.MilestoneCount) completed
## MANDATORY Before ANY Response to the User
You MUST complete these steps before responding to any user message, including simple greetings:
1. Read `~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md` (mission lifecycle protocol)
2. Read `docs/MISSION-MANIFEST.md` for full mission scope, milestones, and success criteria
3. Read the latest scratchpad in `docs/scratchpads/` for session history, decisions, and corrections
4. Read `docs/TASKS.md` for current task state (what is done, what is next)
5. After reading all four, acknowledge the mission state to the user before proceeding
If the user gives a task, execute it within the mission context. If no task is given, present mission status and ask how to proceed.
"@
}
function Get-MissionPrompt {
$mission = Get-ActiveMission
if ($null -eq $mission) {
return ""
}
return "Active mission detected: $($mission.Name). Read the mission state files and report status."
}
function Get-RuntimePrompt {
param(
[ValidateSet("claude", "codex", "opencode")]
[string]$Runtime
)
$runtimeFile = switch ($Runtime) {
"claude" { Join-Path $MosaicHome "runtime\claude\RUNTIME.md" }
"codex" { Join-Path $MosaicHome "runtime\codex\RUNTIME.md" }
"opencode" { Join-Path $MosaicHome "runtime\opencode\RUNTIME.md" }
}
if (-not (Test-Path $runtimeFile)) {
Write-Host "[mosaic] ERROR: runtime contract not found: $runtimeFile" -ForegroundColor Red
exit 1
}
$launcherContract = @'
# Mosaic Launcher Runtime Contract (Hard Gate)
This contract is injected by `mosaic` launch and is mandatory.
First assistant response MUST start with exactly one mode declaration line:
1. Orchestration mission: `Now initiating Orchestrator mode...`
2. Implementation mission: `Now initiating Delivery mode...`
3. Review-only mission: `Now initiating Review mode...`
No tool call or implementation step may occur before that first line.
Mosaic hard gates OVERRIDE runtime-default caution for routine delivery operations.
For required push/merge/issue-close/release actions, execute without routine confirmation prompts.
'@
$missionBlock = Get-MissionContractBlock
$agentsContent = Get-Content (Join-Path $MosaicHome "AGENTS.md") -Raw
$runtimeContent = Get-Content $runtimeFile -Raw
if (-not [string]::IsNullOrWhiteSpace($missionBlock)) {
return "$missionBlock`n`n$launcherContract`n$agentsContent`n`n# Runtime-Specific Contract`n`n$runtimeContent"
}
return "$launcherContract`n$agentsContent`n`n# Runtime-Specific Contract`n`n$runtimeContent"
}
function Ensure-RuntimeConfig {
param(
[ValidateSet("claude", "codex", "opencode")]
[string]$Runtime,
[string]$Dst
)
$parent = Split-Path $Dst -Parent
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
$runtimePrompt = Get-RuntimePrompt -Runtime $Runtime
$tmp = [System.IO.Path]::GetTempFileName()
Set-Content -Path $tmp -Value $runtimePrompt -Encoding UTF8 -NoNewline
$srcHash = (Get-FileHash $tmp -Algorithm SHA256).Hash
$dstHash = if (Test-Path $Dst) { (Get-FileHash $Dst -Algorithm SHA256).Hash } else { "" }
if ($srcHash -ne $dstHash) {
Copy-Item $tmp $Dst -Force
Remove-Item $tmp -Force
}
else {
Remove-Item $tmp -Force
}
}
function Invoke-Yolo {
param([string[]]$YoloArgs)
if ($YoloArgs.Count -lt 1) {
Write-Host "[mosaic] ERROR: yolo requires a runtime (claude|codex|opencode)." -ForegroundColor Red
Write-Host "[mosaic] Example: mosaic yolo claude"
exit 1
}
$runtime = $YoloArgs[0]
$tail = if ($YoloArgs.Count -gt 1) { @($YoloArgs[1..($YoloArgs.Count - 1)]) } else { @() }
switch ($runtime) {
"claude" {
Assert-MosaicHome
Assert-AgentsMd
Assert-Soul
Assert-Runtime "claude"
Assert-SequentialThinking
$agentsContent = Get-RuntimePrompt -Runtime "claude"
Write-Host "[mosaic] Launching Claude Code in YOLO mode (dangerous permissions enabled)..."
& claude --dangerously-skip-permissions --append-system-prompt $agentsContent @tail
return
}
"codex" {
Assert-MosaicHome
Assert-AgentsMd
Assert-Soul
Assert-Runtime "codex"
Assert-SequentialThinking
Ensure-RuntimeConfig -Runtime "codex" -Dst (Join-Path $env:USERPROFILE ".codex\instructions.md")
$missionPrompt = Get-MissionPrompt
if (-not [string]::IsNullOrWhiteSpace($missionPrompt) -and $tail.Count -eq 0) {
Write-Host "[mosaic] Launching Codex in YOLO mode (active mission detected)..."
& codex --dangerously-bypass-approvals-and-sandbox $missionPrompt
}
else {
Write-Host "[mosaic] Launching Codex in YOLO mode (dangerous permissions enabled)..."
& codex --dangerously-bypass-approvals-and-sandbox @tail
}
return
}
"opencode" {
Assert-MosaicHome
Assert-AgentsMd
Assert-Soul
Assert-Runtime "opencode"
Assert-SequentialThinking
Ensure-RuntimeConfig -Runtime "opencode" -Dst (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md")
Write-Host "[mosaic] Launching OpenCode in YOLO mode..."
& opencode @tail
return
}
default {
Write-Host "[mosaic] ERROR: Unsupported yolo runtime '$runtime'. Use claude|codex|opencode." -ForegroundColor Red
exit 1
}
}
}
if ($args.Count -eq 0) {
Show-Usage
exit 0
}
$command = $args[0]
$remaining = if ($args.Count -gt 1) { @($args[1..($args.Count - 1)]) } else { @() }
switch ($command) {
"claude" {
Assert-MosaicHome
Assert-AgentsMd
Assert-Soul
Assert-Runtime "claude"
Assert-SequentialThinking
# Claude supports --append-system-prompt for direct injection
$agentsContent = Get-RuntimePrompt -Runtime "claude"
Write-Host "[mosaic] Launching Claude Code..."
& claude --append-system-prompt $agentsContent @remaining
}
"opencode" {
Assert-MosaicHome
Assert-AgentsMd
Assert-Soul
Assert-Runtime "opencode"
Assert-SequentialThinking
# OpenCode reads from ~/.config/opencode/AGENTS.md
Ensure-RuntimeConfig -Runtime "opencode" -Dst (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md")
Write-Host "[mosaic] Launching OpenCode..."
& opencode @remaining
}
"codex" {
Assert-MosaicHome
Assert-AgentsMd
Assert-Soul
Assert-Runtime "codex"
Assert-SequentialThinking
# Codex reads from ~/.codex/instructions.md
Ensure-RuntimeConfig -Runtime "codex" -Dst (Join-Path $env:USERPROFILE ".codex\instructions.md")
$missionPrompt = Get-MissionPrompt
if (-not [string]::IsNullOrWhiteSpace($missionPrompt) -and $remaining.Count -eq 0) {
Write-Host "[mosaic] Launching Codex (active mission detected)..."
& codex $missionPrompt
}
else {
Write-Host "[mosaic] Launching Codex..."
& codex @remaining
}
}
"yolo" {
Invoke-Yolo -YoloArgs $remaining
}
"--yolo" {
Invoke-Yolo -YoloArgs $remaining
}
"init" {
Assert-MosaicHome
& (Join-Path $MosaicHome "bin\mosaic-init.ps1") @remaining
}
"doctor" {
Assert-MosaicHome
& (Join-Path $MosaicHome "bin\mosaic-doctor.ps1") @remaining
}
"sync" {
Assert-MosaicHome
& (Join-Path $MosaicHome "bin\mosaic-sync-skills.ps1") @remaining
}
"bootstrap" {
Assert-MosaicHome
Write-Host "[mosaic] NOTE: mosaic-bootstrap-repo requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-bootstrap-repo") @remaining
}
"upgrade" {
Assert-MosaicHome
if ($remaining.Count -eq 0) {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1")
break
}
$mode = $remaining[0]
$tail = if ($remaining.Count -gt 1) { $remaining[1..($remaining.Count - 1)] } else { @() }
switch -Regex ($mode) {
"^release$" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @tail
}
"^check$" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") -DryRun @tail
}
"^project$" {
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @tail
}
"^(--all|--root)$" {
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
}
"^(--dry-run|--ref|--keep|--overwrite|-y|--yes)$" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
}
"^-.*" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
}
default {
Write-Host "[mosaic] NOTE: treating positional argument as project path." -ForegroundColor Yellow
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
}
}
}
"release-upgrade" {
Assert-MosaicHome
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
}
"project-upgrade" {
Assert-MosaicHome
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
}
{ $_ -in "help", "-h", "--help" } { Show-Usage }
{ $_ -in "version", "-v", "--version" } { Write-Host "mosaic $Version" }
default {
Write-Host "[mosaic] Unknown command: $command" -ForegroundColor Red
Write-Host "[mosaic] Run 'mosaic --help' for usage."
exit 1
}
}

View File

@@ -0,0 +1,139 @@
# Mosaic Framework Consistency Audit
Date: 2026-02-17
Scope:
- `~/src/mosaic-bootstrap`
- `~/src/agent-skills`
- Installed runtime check: `~/.config/mosaic`
## Findings
| ID | Severity | Finding | Status |
| ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| MF-001 | High | QA rails scripts referenced invalid paths (missing `/qa/` segment) for `qa-hook-handler.sh` calls. | Remediated |
| MF-002 | Medium | Conditional-loading detection was biased to legacy `agent-guides` markers and missed Mosaic `guides`/`Conditional Context` phrasing. | Remediated |
| MF-003 | Medium | Framework spec text still described detection as `agent-guides`-based only. | Remediated |
| MF-004 | Medium | Runtime Claude overlay hardcoded skill count, which drifts over time. | Remediated |
| MF-005 | High | `pr-reviewer` skill used legacy `~/.claude/scripts/git` and `~/.claude/skills` paths. | Remediated |
| MF-006 | Medium | `using-git-worktrees` prioritized `CLAUDE.md` only and ignored Mosaic-first docs (`AGENTS.md`/`SOUL.md`). | Remediated |
| MF-007 | Medium | Marketing skills used `.claude/product-marketing-context.md` instead of Mosaic repo-local path. | Remediated |
| MF-008 | Low | `agent-skills/README.md` manual install/adaptation guidance referenced legacy Claude-only paths. | Remediated |
| MF-009 | Low | Historical creation-log contained stale Claude-specific path examples. | Remediated |
## Remediation Details
### MF-001 (QA rails path correction)
Updated:
- `tools/qa/qa-hook-wrapper.sh`
- `tools/qa/qa-hook-stdin.sh`
- `tools/qa/qa-hook-handler.sh`
- `tools/qa/remediation-hook-handler.sh`
- `tools/qa/qa-queue-monitor.sh`
Change:
- Standardized handler paths to `~/.config/mosaic/tools/qa/...`.
### MF-002 + MF-003 (conditional loading/context detection)
Updated:
- `tools/bootstrap/agent-lint.sh`
- `tools/bootstrap/agent-upgrade.sh`
- `templates/agent/SPEC.md`
Change:
- Detection now recognizes both legacy and Mosaic patterns:
- `agent-guides` (legacy compatibility)
- `~/.config/mosaic/guides`
- `Conditional Loading`
- `Conditional Context`
### MF-004 (runtime overlay drift-proofing)
Updated:
- `runtime/claude/CLAUDE.md`
Change:
- Removed hardcoded skills count text.
### MF-005 (pr-reviewer skill path migration)
Updated:
- `skills/pr-reviewer/SKILL.md`
Change:
- Replaced all `~/.claude/scripts/git/...` with `~/.config/mosaic/tools/git/...`.
- Replaced `~/.claude/skills/...` with `~/.config/mosaic/skills/...`.
### MF-006 (worktree skill docs hierarchy)
Updated:
- `skills/using-git-worktrees/SKILL.md`
Change:
- Replaced CLAUDE-only checks with `AGENTS.md` / `SOUL.md` (fallback: `CLAUDE.md`).
### MF-007 (marketing context path migration)
Updated:
- `skills/product-marketing-context/SKILL.md`
- All skills referencing product-marketing-context path (bulk update)
Change:
- Standardized context path to `.mosaic/product-marketing-context.md`.
### MF-008 + MF-009 (repo guidance cleanup)
Updated:
- `README.md` (agent-skills)
- `skills/writing-skills/SKILL.md`
- `skills/writing-skills/examples/CLAUDE_MD_TESTING.md`
- `skills/systematic-debugging/CREATION-LOG.md`
Change:
- Standardized references to `~/.config/mosaic/skills`.
- Removed stale Claude-only wording.
## Residual Legacy References (Intentional)
The following legacy references remain in `mosaic-bootstrap` by design and are not inconsistencies:
- Runtime compatibility tooling for Claude home directory management:
- `bin/mosaic-link-runtime-assets`
- `bin/mosaic-clean-runtime`
- `bin/mosaic-doctor`
- `bin/mosaic-sync-skills`
- `bin/mosaic-migrate-local-skills`
- Documentation explaining Claude runtime overlays:
- `README.md`
- `profiles/README.md`
- `adapters/claude.md`
- `runtime/claude/settings-overlays/jarvis-loop.json`
These are required to support existing Claude runtime integration while keeping Mosaic as canonical source.
## Verification
Executed checks:
- `rg -n "~/.claude|\\.claude/|agent-guides" ~/src/agent-skills -S`
- Result: no matches after remediation.
- `rg -n "~/.config/mosaic/tools/(qa-hook|remediation-hook|qa-queue-monitor)" ~/src/mosaic-bootstrap -S`
- Result: no invalid old-style QA rail paths remain.
- Installed runtime validation:
- `~/.config/mosaic` contains `tools/git`, `tools/portainer`, `tools/cicd`, `skills`, and `bin` tooling.

View File

@@ -0,0 +1,193 @@
# Authentication & Authorization Guide
## Before Starting
1. Check assigned issue: `~/.config/mosaic/tools/git/issue-list.sh -a @me`
2. Review existing auth implementation in codebase
3. Review Vault secrets structure: `docs/vault-secrets-structure.md`
## Authentication Patterns
### JWT (JSON Web Tokens)
```
Vault Path: secret-{env}/backend-api/jwt/signing-key
Fields: key, algorithm, expiry_seconds
```
**Best Practices:**
- Use RS256 or ES256 (asymmetric) for distributed systems
- Use HS256 (symmetric) only for single-service auth
- Set reasonable expiry (15min-1hr for access tokens)
- Include minimal claims (sub, exp, iat, roles)
- Never store sensitive data in JWT payload
### Session-Based
```
Vault Path: secret-{env}/{service}/session/secret
Fields: secret, cookie_name, max_age
```
**Best Practices:**
- Use secure, httpOnly, sameSite cookies
- Regenerate session ID on privilege change
- Implement session timeout
- Store sessions server-side (Redis/database)
### OAuth2/OIDC
```
Vault Paths:
- secret-{env}/{service}/oauth/{provider}/client_id
- secret-{env}/{service}/oauth/{provider}/client_secret
```
**Best Practices:**
- Use PKCE for public clients
- Validate state parameter
- Verify token signatures
- Check issuer and audience claims
## Authorization Patterns
### Role-Based Access Control (RBAC)
```python
# Example middleware
def require_role(roles: list):
def decorator(handler):
def wrapper(request):
user_roles = get_user_roles(request.user_id)
if not any(role in user_roles for role in roles):
raise ForbiddenError()
return handler(request)
return wrapper
return decorator
@require_role(['admin', 'moderator'])
def delete_user(request):
pass
```
### Permission-Based
```python
# Check specific permissions
def check_permission(user_id, resource, action):
permissions = get_user_permissions(user_id)
return f"{resource}:{action}" in permissions
```
## Security Requirements
### Password Handling
- Use bcrypt, scrypt, or Argon2 for hashing
- Minimum 12 character passwords
- Check against breached password lists
- Implement account lockout after failed attempts
### Token Security
- Rotate secrets regularly
- Implement token revocation
- Use short-lived access tokens with refresh tokens
- Store refresh tokens securely (httpOnly cookies or encrypted storage)
### Multi-Factor Authentication
- Support TOTP (Google Authenticator compatible)
- Consider WebAuthn for passwordless
- Require MFA for sensitive operations
## Testing Authentication
### Test Cases Required
```python
class TestAuthentication:
def test_login_success_returns_token(self):
pass
def test_login_failure_returns_401(self):
pass
def test_invalid_token_returns_401(self):
pass
def test_expired_token_returns_401(self):
pass
def test_missing_token_returns_401(self):
pass
def test_insufficient_permissions_returns_403(self):
pass
def test_token_refresh_works(self):
pass
def test_logout_invalidates_token(self):
pass
```
## Authentik SSO Administration
Authentik is the identity provider for the Mosaic Stack. Use the Authentik tool suite for administration.
### Tool Suite
```bash
# System health
~/.config/mosaic/tools/authentik/admin-status.sh
# User management
~/.config/mosaic/tools/authentik/user-list.sh
~/.config/mosaic/tools/authentik/user-create.sh -u <username> -n <name> -e <email>
# Group and app management
~/.config/mosaic/tools/authentik/group-list.sh
~/.config/mosaic/tools/authentik/app-list.sh
~/.config/mosaic/tools/authentik/flow-list.sh
```
### Registering an OAuth Application
1. Create an OAuth2 provider in Authentik admin (Applications > Providers)
2. Create an application linked to the provider (Applications > Applications)
3. Configure redirect URIs for the application
4. Store client_id and client_secret in Vault: `secret-{env}/{service}/oauth/authentik/`
5. Verify with: `~/.config/mosaic/tools/authentik/app-list.sh`
### API Reference
- Base URL: `https://auth.diversecanvas.com`
- API prefix: `/api/v3/`
- OpenAPI schema: `/api/v3/schema/`
- Auth: Bearer token (obtained via `auth-token.sh`)
## Common Vulnerabilities to Avoid
1. **Broken Authentication**
- Weak password requirements
- Missing brute-force protection
- Session fixation
2. **Broken Access Control**
- Missing authorization checks
- IDOR (Insecure Direct Object Reference)
- Privilege escalation
3. **Security Misconfiguration**
- Default credentials
- Verbose error messages
- Missing security headers
## Commit Format
```
feat(#89): Implement JWT authentication
- Add /auth/login and /auth/refresh endpoints
- Implement token validation middleware
- Configure 15min access token expiry
Fixes #89
```

View File

@@ -0,0 +1,125 @@
# Backend Development Guide
## Before Starting
1. Check assigned issue: `~/.config/mosaic/tools/git/issue-list.sh -a @me`
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
3. Review API contracts and database schema
## Development Standards
### API Design
- Follow RESTful conventions (or GraphQL patterns if applicable)
- Use consistent endpoint naming: `/api/v1/resource-name`
- Return appropriate HTTP status codes
- Include pagination for list endpoints
- Document all endpoints (OpenAPI/Swagger preferred)
### Database
- Write migrations for schema changes
- Use parameterized queries (prevent SQL injection)
- Index frequently queried columns
- Document relationships and constraints
### Error Handling
- Return structured error responses
- Log errors with context (request ID, user ID if applicable)
- Never expose internal errors to clients
- Use appropriate error codes
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "User-friendly message",
"details": []
}
}
```
### Security
- Validate all input at API boundaries
- Implement rate limiting on public endpoints
- Use secrets from Vault (see `docs/vault-secrets-structure.md`)
- Never log sensitive data (passwords, tokens, PII)
- Follow OWASP guidelines
### Authentication/Authorization
- Use project's established auth pattern
- Validate tokens on every request
- Check permissions before operations
- See `~/.config/mosaic/guides/AUTHENTICATION.md` for details
## Testing Requirements (TDD)
1. Write tests BEFORE implementation
2. Minimum 85% coverage
3. Test categories:
- Unit tests for business logic
- Integration tests for API endpoints
- Database tests with transactions/rollback
### Test Patterns
```python
# API test example structure
class TestResourceEndpoint:
def test_create_returns_201(self):
pass
def test_create_validates_input(self):
pass
def test_get_returns_404_for_missing(self):
pass
def test_requires_authentication(self):
pass
```
## Code Style
- Follow Google Style Guide for your language
- **TypeScript: Follow `~/.config/mosaic/guides/TYPESCRIPT.md` — MANDATORY**
- Use linter/formatter from project configuration
- Keep functions focused and small
- Document complex business logic
### TypeScript Quick Rules (see TYPESCRIPT.md for full guide)
- **NO `any`** — define explicit types always
- **NO lazy `unknown`** — only for error catches and external data with validation
- **Explicit return types** on all exported functions
- **Explicit parameter types** always
- **DTO files are REQUIRED** for module/API boundaries (`*.dto.ts`)
- **Interface for DTOs** — never inline object types
- **Typed errors** — use custom error classes
## Performance
- Use database connection pooling
- Implement caching where appropriate
- Profile slow endpoints
- Use async operations for I/O
## Commit Format
```
feat(#45): Add user registration endpoint
- POST /api/v1/users for registration
- Email validation and uniqueness check
- Password hashing with bcrypt
Fixes #45
```
## Before Completing
1. Run full test suite
2. Verify migrations work (up and down)
3. Test API with curl/httpie
4. Update scratchpad with completion notes
5. Reference issue in commit

View File

@@ -0,0 +1,487 @@
# Project Bootstrap Guide
> Load this guide when setting up a new project for AI-assisted development.
## Overview
This guide covers how to bootstrap a project so AI agents (Claude, Codex, etc.) can work on it effectively. Proper bootstrapping ensures:
1. Agents understand the project structure and conventions
2. Orchestration works correctly with quality gates
3. Independent code review and security review are configured
4. Issue tracking is consistent across projects
5. Documentation standards and API contracts are enforced from day one
6. PRD requirements are established before coding begins
7. Branching/merging is consistent: `branch -> main` via PR with squash-only merges
8. Steered-autonomy execution is enabled so agents can run end-to-end with escalation-only human intervention
## Quick Start
```bash
# Automated bootstrap (recommended)
~/.config/mosaic/tools/bootstrap/init-project.sh \
--name "my-project" \
--type "nestjs-nextjs" \
--repo "https://git.mosaicstack.dev/owner/repo"
# Or manually using templates
export PROJECT_NAME="My Project"
export PROJECT_DESCRIPTION="What this project does"
export TASK_PREFIX="MP"
envsubst < ~/.config/mosaic/templates/agent/AGENTS.md.template > AGENTS.md
envsubst < ~/.config/mosaic/templates/agent/CLAUDE.md.template > CLAUDE.md
```
---
## Step 0: Enforce Sequential-Thinking MCP (Hard Requirement)
`sequential-thinking` MCP must be installed and configured before project bootstrapping.
```bash
# Auto-configure sequential-thinking MCP for installed runtimes
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking
# Verification-only check
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking --check
```
If this step fails, STOP and remediate Mosaic runtime configuration before continuing.
---
## Step 1: Detect Project Type
Check what files exist in the project root to determine the type:
| File Present | Project Type | Template |
| ------------------------------------------------------- | ------------------------- | ------------------------- |
| `package.json` + `pnpm-workspace.yaml` + NestJS+Next.js | NestJS + Next.js Monorepo | `projects/nestjs-nextjs/` |
| `pyproject.toml` + `manage.py` | Django | `projects/django/` |
| `pyproject.toml` (no Django) | Python (generic) | Generic template |
| `package.json` (no monorepo) | Node.js (generic) | Generic template |
| Other | Generic | Generic template |
```bash
# Auto-detect project type
detect_project_type() {
if [[ -f "pnpm-workspace.yaml" ]] && [[ -f "turbo.json" ]]; then
# Check for NestJS + Next.js
if grep -q "nestjs" package.json 2>/dev/null && grep -q "next" package.json 2>/dev/null; then
echo "nestjs-nextjs"
return
fi
fi
if [[ -f "manage.py" ]] && [[ -f "pyproject.toml" ]]; then
echo "django"
return
fi
if [[ -f "pyproject.toml" ]]; then
echo "python"
return
fi
if [[ -f "package.json" ]]; then
echo "nodejs"
return
fi
echo "generic"
}
```
---
## Step 2: Create AGENTS.md (Primary Project Contract)
`AGENTS.md` is the primary project-level contract for all agent runtimes.
It defines project-specific requirements, quality gates, patterns, and testing expectations.
### Using a Tech-Stack Template
```bash
# Set variables
export PROJECT_NAME="My Project"
export PROJECT_DESCRIPTION="Multi-tenant SaaS platform"
export PROJECT_DIR="my-project"
export REPO_URL="https://git.mosaicstack.dev/owner/repo"
export TASK_PREFIX="MP"
# Use tech-stack-specific template if available
TYPE=$(detect_project_type)
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent/projects/$TYPE"
if [[ -d "$TEMPLATE_DIR" ]]; then
envsubst < "$TEMPLATE_DIR/AGENTS.md.template" > AGENTS.md
else
envsubst < "$HOME/.config/mosaic/templates/agent/AGENTS.md.template" > AGENTS.md
fi
```
### Using the Generic Template
```bash
# Set all required variables
export PROJECT_NAME="My Project"
export PROJECT_DESCRIPTION="What this project does"
export REPO_URL="https://git.mosaicstack.dev/owner/repo"
export PROJECT_DIR="my-project"
export SOURCE_DIR="src"
export CONFIG_FILES="pyproject.toml / package.json"
export FRONTEND_STACK="N/A"
export BACKEND_STACK="Python / FastAPI"
export DATABASE_STACK="PostgreSQL"
export TESTING_STACK="pytest"
export DEPLOYMENT_STACK="Docker"
export BUILD_COMMAND="pip install -e ."
export TEST_COMMAND="pytest tests/"
export LINT_COMMAND="ruff check ."
export TYPECHECK_COMMAND="mypy ."
export QUALITY_GATES="ruff check . && mypy . && pytest tests/"
envsubst < ~/.config/mosaic/templates/agent/AGENTS.md.template > AGENTS.md
```
### Required Sections
Every AGENTS.md should contain:
1. **Project description** — One-line summary
2. **Quality gates** — Commands that must pass
3. **Codebase patterns** — Reusable implementation rules
4. **Common gotchas** — Non-obvious constraints
5. **Testing approaches** — Project-specific test strategy
6. **Testing policy** — Situational-first validation and risk-based TDD
7. **Orchestrator integration** — Task prefix, worker checklist
8. **Documentation contract** — Required documentation gates and update expectations
9. **PRD requirement**`docs/PRD.md` or `docs/PRD.json` required before coding
---
## Step 3: Create Runtime Context File (Runtime-Specific)
Runtime context files are runtime adapters. They are not the primary project contract.
Use `CLAUDE.md` for Claude runtime compatibility. Use other runtime adapters as required by your environment.
Claude runtime mandate (HARD RULE):
- `CLAUDE.md` MUST explicitly instruct Claude agents to read and use `AGENTS.md`.
- `CLAUDE.md` MUST treat `AGENTS.md` as the authoritative project-level contract.
- If `AGENTS.md` and runtime wording conflict, `AGENTS.md` project rules win.
```bash
TYPE=$(detect_project_type)
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent/projects/$TYPE"
if [[ -d "$TEMPLATE_DIR" ]]; then
envsubst < "$TEMPLATE_DIR/CLAUDE.md.template" > CLAUDE.md
else
envsubst < "$HOME/.config/mosaic/templates/agent/CLAUDE.md.template" > CLAUDE.md
fi
```
### Required Runtime Sections
Every runtime context file should contain:
1. **AGENTS handoff rule** — Runtime MUST direct agents to read/use `AGENTS.md`
2. **Conditional documentation loading** — Required guide loading map
3. **Technology stack** — Runtime-facing architecture summary
4. **Repository structure** — Important paths
5. **Development workflow** — Build/test/lint/typecheck commands
6. **Issue tracking** — Issue and commit conventions
7. **Code review** — Required review process
8. **Runtime notes** — Runtime-specific behavior references
9. **Branch and merge policy** — Trunk workflow (`branch -> main` via PR, squash-only)
10. **Autonomy and escalation policy** — Agent owns coding/review/PR/release/deploy lifecycle
---
## Step 4: Create Directory Structure
```bash
# Create standard directories
mkdir -p docs/scratchpads
mkdir -p docs/templates
mkdir -p docs/reports/qa-automation/pending
mkdir -p docs/reports/qa-automation/in-progress
mkdir -p docs/reports/qa-automation/done
mkdir -p docs/reports/qa-automation/escalated
mkdir -p docs/reports/deferred
mkdir -p docs/tasks
mkdir -p docs/releases
mkdir -p docs/USER-GUIDE docs/ADMIN-GUIDE docs/DEVELOPER-GUIDE docs/API
# Documentation baseline files
touch docs/USER-GUIDE/README.md
touch docs/ADMIN-GUIDE/README.md
touch docs/DEVELOPER-GUIDE/README.md
touch docs/API/OPENAPI.yaml
touch docs/API/ENDPOINTS.md
touch docs/SITEMAP.md
# PRD baseline file (requirements source before coding)
cp ~/.config/mosaic/templates/docs/PRD.md.template docs/PRD.md
# TASKS baseline file (canonical tracking)
cp ~/.config/mosaic/templates/docs/TASKS.md.template docs/TASKS.md
# Deployment baseline file (target/platform/runbook)
touch docs/DEPLOYMENT.md
```
Documentation root hygiene (HARD RULE):
- Keep `docs/` root clean.
- Store reports in `docs/reports/`, archived task artifacts in `docs/tasks/`, releases in `docs/releases/`, and scratchpads in `docs/scratchpads/`.
- Do not place ad-hoc report files directly under `docs/`.
---
## Step 5: Initialize Repository Labels & Milestones
```bash
# Use the init script
~/.config/mosaic/tools/bootstrap/init-repo-labels.sh
# Or manually create standard labels
~/.config/mosaic/tools/git/issue-create.sh # (labels are created on first use)
```
### Standard Labels
| Label | Color | Purpose |
| --------------- | --------- | -------------------------------------- |
| `epic` | `#3E4B9E` | Large feature spanning multiple issues |
| `feature` | `#0E8A16` | New functionality |
| `bug` | `#D73A4A` | Defect fix |
| `task` | `#0075CA` | General work item |
| `documentation` | `#0075CA` | Documentation updates |
| `security` | `#B60205` | Security-related |
| `breaking` | `#D93F0B` | Breaking change |
### Initial Milestone (Hard Rule)
Create the first pre-MVP milestone at `0.0.1`.
Reserve `0.1.0` for the MVP release milestone.
```bash
~/.config/mosaic/tools/git/milestone-create.sh -t "0.0.1" -d "Pre-MVP - Foundation Sprint"
# Create when MVP scope is complete and release-ready:
~/.config/mosaic/tools/git/milestone-create.sh -t "0.1.0" -d "MVP - Minimum Viable Product"
```
---
## Step 5b: Configure Main Branch Protection (Hard Rule)
Apply equivalent settings in Gitea, GitHub, or GitLab:
1. Protect `main` from direct pushes.
2. Require pull requests to merge into `main`.
3. Require required CI/status checks to pass before merge.
4. Require code review approval before merge.
5. Allow **squash merge only** for PRs into `main` (disable merge commits and rebase merges for `main`).
This enforces one merge strategy across human and agent workflows.
---
## Step 6: Set Up CI/CD Review Pipeline
### Woodpecker CI
```bash
# Copy Codex review pipeline
mkdir -p .woodpecker/schemas
cp ~/.config/mosaic/tools/codex/woodpecker/codex-review.yml .woodpecker/
cp ~/.config/mosaic/tools/codex/schemas/*.json .woodpecker/schemas/
# Add codex_api_key secret to Woodpecker CI dashboard
```
### GitHub Actions
For GitHub repos, use the official Codex GitHub Action instead:
```yaml
# .github/workflows/codex-review.yml
uses: openai/codex-action@v1
```
### Python Package Publishing (Gitea PyPI)
If the project publishes Python packages, use Gitea's PyPI registry.
```bash
# Build and publish
python -m pip install --upgrade build twine
python -m build
python -m twine upload \
--repository-url "https://GITEA_HOST/api/packages/ORG/pypi" \
--username "$GITEA_USERNAME" \
--password "$GITEA_TOKEN" \
dist/*
```
Use the same `gitea_username` and `gitea_token` CI secrets used for container and npm publishing.
---
## Step 7: Verify Bootstrap
After bootstrapping, verify everything works:
```bash
# Check files exist
ls AGENTS.md docs/scratchpads/
ls docs/reports/qa-automation/pending docs/reports/deferred docs/tasks docs/releases
ls docs/USER-GUIDE/README.md docs/ADMIN-GUIDE/README.md docs/DEVELOPER-GUIDE/README.md
ls docs/API/OPENAPI.yaml docs/API/ENDPOINTS.md docs/SITEMAP.md
ls docs/PRD.md
ls docs/TASKS.md
# Verify AGENTS.md has required sections
grep -c "Quality Gates" AGENTS.md
grep -c "Orchestrator Integration" AGENTS.md
grep -c "Testing Approaches" AGENTS.md
grep -c "Testing Policy" AGENTS.md
grep -c "Documentation Contract" AGENTS.md
grep -c "PRD Requirement" AGENTS.md
# Verify runtime context file has required sections
if [[ -f CLAUDE.md ]]; then
grep -c "AGENTS.md" CLAUDE.md
grep -c "Conditional Documentation Loading" CLAUDE.md
grep -c "Technology Stack" CLAUDE.md
grep -c "Code Review" CLAUDE.md
elif [[ -f RUNTIME.md ]]; then
grep -c "Conditional Documentation Loading" RUNTIME.md
grep -c "Technology Stack" RUNTIME.md
grep -c "Code Review" RUNTIME.md
else
echo "Missing runtime context file (CLAUDE.md or RUNTIME.md)" >&2
exit 1
fi
# Run quality gates from AGENTS.md
# (execute the command block under "Quality Gates")
# Test Codex review (if configured)
~/.config/mosaic/tools/codex/codex-code-review.sh --help
# Verify sequential-thinking MCP remains configured
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking --check
```
---
## Available Templates
### Generic Templates
| Template | Path | Purpose |
| ---------------------------- | ----------------------------------- | ------------------------------------------ |
| `AGENTS.md.template` | `~/.config/mosaic/templates/agent/` | Primary project agent contract |
| `CLAUDE.md.template` | `~/.config/mosaic/templates/agent/` | Runtime compatibility context (Claude) |
| `DOCUMENTATION-CHECKLIST.md` | `~/.config/mosaic/templates/docs/` | Documentation completion gate |
| `PRD.md.template` | `~/.config/mosaic/templates/docs/` | Requirements source template |
| `TASKS.md.template` | `~/.config/mosaic/templates/docs/` | Canonical task and issue tracking template |
### Tech-Stack Templates
| Stack | Path | Includes |
| ---------------- | ---------------------------------------------------------- | ------------------------------------ |
| NestJS + Next.js | `~/.config/mosaic/templates/agent/projects/nestjs-nextjs/` | AGENTS.md + runtime context template |
| Django | `~/.config/mosaic/templates/agent/projects/django/` | AGENTS.md + runtime context template |
### Orchestrator Templates
| Template | Path | Purpose |
| -------------------------------------- | ------------------------------------------------- | ----------------------- |
| `tasks.md.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Task tracking |
| `orchestrator-learnings.json.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Variance tracking |
| `phase-issue-body.md.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Git provider issue body |
| `scratchpad.md.template` | `~/src/jarvis-brain/docs/templates/` | Per-task working doc |
### Variables Reference
| Variable | Description | Example |
| ------------------------ | --------------------------- | ------------------------------------------ |
| `${PROJECT_NAME}` | Human-readable project name | "Mosaic Stack" |
| `${PROJECT_DESCRIPTION}` | One-line description | "Multi-tenant platform" |
| `${PROJECT_DIR}` | Directory name | "mosaic-stack" |
| `${PROJECT_SLUG}` | Python package slug | "mosaic_stack" |
| `${REPO_URL}` | Git remote URL | "https://git.mosaicstack.dev/mosaic/stack" |
| `${TASK_PREFIX}` | Orchestrator task prefix | "MS" |
| `${SOURCE_DIR}` | Source code directory | "src" or "apps" |
| `${QUALITY_GATES}` | Quality gate commands | "pnpm typecheck && pnpm lint && pnpm test" |
| `${BUILD_COMMAND}` | Build command | "pnpm build" |
| `${TEST_COMMAND}` | Test command | "pnpm test" |
| `${LINT_COMMAND}` | Lint command | "pnpm lint" |
| `${TYPECHECK_COMMAND}` | Type check command | "pnpm typecheck" |
| `${FRONTEND_STACK}` | Frontend technologies | "Next.js + React" |
| `${BACKEND_STACK}` | Backend technologies | "NestJS + Prisma" |
| `${DATABASE_STACK}` | Database technologies | "PostgreSQL" |
| `${TESTING_STACK}` | Testing technologies | "Vitest + Playwright" |
| `${DEPLOYMENT_STACK}` | Deployment technologies | "Docker" |
| `${CONFIG_FILES}` | Key config files | "package.json, tsconfig.json" |
---
## Bootstrap Scripts
### init-project.sh
Full project bootstrap with interactive and flag-based modes:
```bash
~/.config/mosaic/tools/bootstrap/init-project.sh \
--name "My Project" \
--type "nestjs-nextjs" \
--repo "https://git.mosaicstack.dev/owner/repo" \
--prefix "MP" \
--description "Multi-tenant platform"
```
### init-repo-labels.sh
Initialize standard labels and the first pre-MVP milestone:
```bash
~/.config/mosaic/tools/bootstrap/init-repo-labels.sh
```
---
## Checklist
After bootstrapping, verify:
- [ ] `AGENTS.md` exists and is the primary project contract
- [ ] Runtime context file exists (`CLAUDE.md` or `RUNTIME.md`)
- [ ] `docs/scratchpads/` directory exists
- [ ] `docs/reports/qa-automation/pending` directory exists
- [ ] `docs/reports/deferred/` directory exists
- [ ] `docs/tasks/` directory exists
- [ ] `docs/releases/` directory exists
- [ ] `docs/USER-GUIDE/README.md` exists
- [ ] `docs/ADMIN-GUIDE/README.md` exists
- [ ] `docs/DEVELOPER-GUIDE/README.md` exists
- [ ] `docs/API/OPENAPI.yaml` exists
- [ ] `docs/API/ENDPOINTS.md` exists
- [ ] `docs/SITEMAP.md` exists
- [ ] `docs/PRD.md` or `docs/PRD.json` exists
- [ ] `docs/TASKS.md` exists and is ready for active tracking
- [ ] `docs/DEPLOYMENT.md` exists with target platform and rollback notes
- [ ] `sequential-thinking` MCP is configured and verification check passes
- [ ] Git labels created (epic, feature, bug, task, etc.)
- [ ] Initial pre-MVP milestone created (0.0.1)
- [ ] MVP milestone reserved for release (0.1.0)
- [ ] `main` is protected from direct pushes
- [ ] PRs into `main` are required
- [ ] Merge method for `main` is squash-only
- [ ] Quality gates run successfully
- [ ] `.env.example` exists (if project uses env vars)
- [ ] CI/CD pipeline configured (if using Woodpecker/GitHub Actions)
- [ ] Python publish path configured in CI (if project ships Python packages)
- [ ] Codex review scripts accessible (`~/.config/mosaic/tools/codex/`)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
# Code Review Guide
## Hard Requirement
If an agent modifies source code, code review is REQUIRED before completion.
Do not mark code-change tasks done until review is completed and blockers are resolved or explicitly tracked.
If code/config/API contract/auth behavior changed and required docs are missing, this is a BLOCKER.
If tests pass but acceptance criteria are not verified by situational evidence, this is a BLOCKER.
If implementation diverges from `docs/PRD.md` or `docs/PRD.json` without PRD updates, this is a BLOCKER.
Merge strategy enforcement (HARD RULE):
- PR target for delivery is `main`.
- Direct pushes to `main` are prohibited.
- Merge to `main` MUST be squash-only.
- Use `~/.config/mosaic/tools/git/pr-merge.sh -n {PR_NUMBER} -m squash` (or PowerShell equivalent).
## Review Checklist
### 1. Correctness
- [ ] Code does what the issue/PR description says
- [ ] Code aligns with active PRD requirements
- [ ] Acceptance criteria are mapped to concrete verification evidence
- [ ] Edge cases are handled
- [ ] Error conditions are managed properly
- [ ] No obvious bugs or logic errors
### 2. Security
- [ ] No hardcoded secrets or credentials
- [ ] Input validation at boundaries
- [ ] SQL injection prevention (parameterized queries)
- [ ] XSS prevention (output encoding)
- [ ] Authentication/authorization checks present
- [ ] Sensitive data not logged
- [ ] Secrets follow Vault structure (see `docs/vault-secrets-structure.md`)
### 2a. OWASP Coverage (Required)
- [ ] OWASP Top 10 categories were reviewed for change impact
- [ ] Access control checks verified on protected actions
- [ ] Cryptographic handling validated (keys, hashing, TLS assumptions)
- [ ] Injection risks reviewed for all untrusted inputs
- [ ] Security misconfiguration risks reviewed (headers, CORS, defaults)
- [ ] Dependency/component risk reviewed (known vulnerable components)
- [ ] Authentication/session flows reviewed for failure paths
- [ ] Logging/monitoring preserves detection without leaking sensitive data
### 3. Testing
- [ ] Tests exist for new functionality
- [ ] Tests cover happy path AND error cases
- [ ] Situational tests cover all impacted change surfaces (primary gate)
- [ ] Tests validate required behavior/outcomes, not only internal implementation details
- [ ] TDD was applied when required by `~/.config/mosaic/guides/QA-TESTING.md`
- [ ] Coverage meets 85% minimum
- [ ] Tests are readable and maintainable
- [ ] No flaky tests introduced
### 4. Code Quality
- [ ] Follows Google Style Guide for the language
- [ ] Functions are focused and reasonably sized
- [ ] No unnecessary complexity
- [ ] DRY - no significant duplication
- [ ] Clear naming for variables and functions
- [ ] No dead code or commented-out code
### 4a. TypeScript Strict Typing (see `TYPESCRIPT.md`)
- [ ] **NO `any` types** — explicit types required everywhere
- [ ] **NO lazy `unknown`** — only for error catches with immediate narrowing
- [ ] **Explicit return types** on all exported/public functions
- [ ] **Explicit parameter types** — never implicit any
- [ ] **No type assertions** (`as Type`) — use type guards instead
- [ ] **No non-null assertions** (`!`) — use proper null handling
- [ ] **Interfaces for objects** — not inline types
- [ ] **Discriminated unions** for variant types
- [ ] **DTO files used at boundaries** — module/API contracts are in `*.dto.ts`, not inline payload types
### 5. Documentation
- [ ] Complex logic has explanatory comments
- [ ] Required docs updated per `~/.config/mosaic/guides/DOCUMENTATION.md`
- [ ] Public APIs are documented
- [ ] Private/internal APIs are documented
- [ ] API input/output schemas are documented
- [ ] API permissions/auth requirements are documented
- [ ] Site map updates are present when navigation changed
- [ ] README updated if needed
- [ ] Breaking changes noted
### 6. Performance
- [ ] No obvious N+1 queries
- [ ] No blocking operations in hot paths
- [ ] Resource cleanup (connections, file handles)
- [ ] Reasonable memory usage
### 7. Dependencies
- [ ] No deprecated packages
- [ ] No unnecessary new dependencies
- [ ] Dependency versions pinned appropriately
## Review Process
Use `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md` whenever code/API/auth/infra changes are present.
### Getting Context
```bash
# List the issue being addressed
~/.config/mosaic/tools/git/issue-list.sh -i {issue-number}
# View the changes
git diff main...HEAD
```
### Providing Feedback
- Be specific: point to exact lines/files
- Explain WHY something is problematic
- Suggest alternatives when possible
- Distinguish between blocking issues and suggestions
- Be constructive, not critical of the person
### Feedback Categories
- **Blocker**: Must fix before merge (security, bugs, test failures)
- **Should Fix**: Important but not blocking (code quality, minor issues)
- **Suggestion**: Optional improvements (style preferences, nice-to-haves)
- **Question**: Seeking clarification
### Review Comment Format
```
[BLOCKER] Line 42: SQL injection vulnerability
The user input is directly interpolated into the query.
Use parameterized queries instead:
`db.query("SELECT * FROM users WHERE id = ?", [userId])`
[SUGGESTION] Line 78: Consider extracting to helper
This pattern appears in 3 places. A shared helper would reduce duplication.
```
## After Review
1. Update issue with review status
2. If changes requested, assign back to author
3. If approved, note approval in issue comments
4. For merges, ensure CI passes first
5. Merge PR to `main` with squash strategy only

View File

@@ -0,0 +1,132 @@
# Documentation Standard (MANDATORY)
This guide defines REQUIRED documentation behavior for all Mosaic projects.
If code, API contracts, auth, or infrastructure changes, documentation updates are REQUIRED before completion.
## Hard Rules
1. Documentation is a delivery gate. Missing required documentation is a BLOCKER.
2. `docs/PRD.md` or `docs/PRD.json` is REQUIRED as the project requirements source before coding begins.
3. API documentation is OpenAPI-first. `docs/API/OPENAPI.yaml` (or `.json`) is the canonical API contract.
4. Public and private/internal endpoints MUST be documented.
5. API input and output schemas MUST be documented.
6. API authentication and permissions MUST be documented per endpoint.
7. A current site map MUST exist at `docs/SITEMAP.md`.
8. Documentation updates MUST be committed in the same logical change set as the code/API change.
9. Generated publishing output (Docusaurus/VitePress/MkDocs artifacts) is not canonical unless the project explicitly declares it canonical.
10. `docs/` root MUST stay clean. Reports and working artifacts MUST be stored in dedicated subdirectories, not dumped at `docs/` root.
## Required Documentation Structure
```text
docs/
PRD.md (or PRD.json)
TASKS.md (active orchestrator tracking, when orchestrator is used)
SITEMAP.md
USER-GUIDE/
ADMIN-GUIDE/
DEVELOPER-GUIDE/
API/
OPENAPI.yaml
ENDPOINTS.md
scratchpads/
reports/
tasks/
releases/
templates/ (optional)
```
Minimum requirements:
- `docs/PRD.md` or `docs/PRD.json`: authoritative requirements source for implementation and testing.
- `docs/USER-GUIDE/`: End-user workflows, feature behavior, common troubleshooting.
- `docs/ADMIN-GUIDE/`: Configuration, deployment, operations, incident/recovery procedures.
- `docs/DEVELOPER-GUIDE/`: Architecture, local setup, contribution/testing workflow, design constraints.
- `docs/API/OPENAPI.yaml`: API SSOT for all HTTP endpoints.
- `docs/API/ENDPOINTS.md`: Human-readable index for API endpoints, permissions, and change notes.
- `docs/SITEMAP.md`: Navigation index for all user/admin/developer/API documentation pages.
- `docs/reports/`: Review outputs, QA automation reports, deferrals, and audit artifacts.
- `docs/tasks/`: Archived task snapshots and orchestrator learnings.
- `docs/releases/`: Release notes and release-specific documentation.
- `docs/scratchpads/`: Active task-level working notes.
## Root Hygiene Rule (MANDATORY)
Allowed root documentation files are intentionally limited:
1. `docs/PRD.md` or `docs/PRD.json`
2. `docs/TASKS.md` (active milestone only, when task orchestration is in use)
3. `docs/SITEMAP.md`
4. `docs/README.md` (optional index)
All other docs MUST be placed in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`, `docs/API/`, guide books).
## Artifact Placement Rules
| Artifact Type | REQUIRED Location |
| ------------------------------------------ | ---------------------------------------- |
| Code review reports, QA reports, audits | `docs/reports/<category>/` |
| Deferred error lists / unresolved findings | `docs/reports/deferred/` |
| Archived milestone task snapshots | `docs/tasks/` |
| Orchestrator learnings JSON | `docs/tasks/orchestrator-learnings.json` |
| Release notes | `docs/releases/` |
| Active scratchpads | `docs/scratchpads/` |
## API Documentation Contract (OpenAPI-First)
For every API endpoint, documentation MUST include:
1. visibility: `public` or `private/internal`
2. method and path
3. endpoint purpose
4. request/input schema
5. response/output schema(s)
6. auth method and required permission/role/scope
7. error status codes and behavior
If OpenAPI cannot fully express an internal constraint, document it in `docs/API/ENDPOINTS.md`.
## Book/Chapter/Page Structure
Use this structure for every guide:
1. Book: one root guide folder (`USER-GUIDE`, `ADMIN-GUIDE`, `DEVELOPER-GUIDE`)
2. Chapter: one subdirectory per topic area
3. Page: one focused markdown file per concern
Required index files:
1. `docs/USER-GUIDE/README.md`
2. `docs/ADMIN-GUIDE/README.md`
3. `docs/DEVELOPER-GUIDE/README.md`
Each index file MUST link to all chapters and pages in that book.
## Situational Documentation Matrix
| Change Surface | REQUIRED Documentation Updates |
| ---------------------------------------------- | ----------------------------------------------------------- |
| New feature or behavior change | User guide + developer guide + sitemap |
| API endpoint added/changed/removed | OpenAPI + API endpoint index + sitemap |
| Auth/RBAC/permission change | API auth/permission docs + admin guide + developer guide |
| Database schema/migration change | Developer guide + admin operational notes if runbook impact |
| CI/CD or deployment change | Admin guide + developer guide |
| Incident, recovery, or security control change | Admin guide runbook + security notes + sitemap |
## Publishing Target Rule (MANDATORY)
If the user does not specify documentation publishing target, the agent MUST ask:
1. Publish in-app (embedded docs)
2. Publish on external docs platform (for example: Docusaurus, VitePress, MkDocs)
Default behavior before publishing decision:
- Keep canonical docs in-repo under `docs/`.
- Do not assume external publishing platform.
## Completion Gate
You MUST NOT declare completion until all required documentation updates are done.
Use `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md` as the final gate.

View File

@@ -0,0 +1,210 @@
# E2E Delivery Procedure (MANDATORY)
This guide is REQUIRED for all agent sessions.
## 0. Mode Handshake (Before Any Action)
First response MUST declare mode before tool calls or implementation steps:
1. Orchestration mission: `Now initiating Orchestrator mode...`
2. Implementation mission: `Now initiating Delivery mode...`
3. Review-only mission: `Now initiating Review mode...`
## 1. PRD Gate (Before Coding)
1. Ensure `docs/PRD.md` or `docs/PRD.json` exists before coding.
2. Load `~/.config/mosaic/guides/PRD.md`.
3. Prepare/update PRD from user input and available project context.
4. If requirements are missing:
- proceed with best-guess assumptions by default,
- mark each assumption with `ASSUMPTION:` and rationale,
- escalate only when uncertainty is high-impact and cannot be bounded safely.
5. Treat PRD as the requirement source for implementation, testing, and review.
## 1a. Tracking Gate (Before Coding)
1. For non-trivial work, `docs/TASKS.md` MUST exist before coding.
2. If `docs/TASKS.md` is missing, create it from `~/.config/mosaic/templates/docs/TASKS.md.template`.
3. Detect provider first via `~/.config/mosaic/tools/git/detect-platform.sh`.
4. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/tools/git/*.sh`).
5. If external git provider is available (Gitea/GitHub/GitLab), create or update issue(s) before coding.
6. Record provider issue reference(s) in `docs/TASKS.md` (example: `#123`).
7. If no external provider is available, use internal task refs in `docs/TASKS.md` (example: `TASKS:T1`).
8. Scratchpad MUST reference both task ID and issue/internal ref.
## 2. Intake and Scope
> **COMPLEXITY TRAP WARNING:** Intake applies to ALL tasks regardless of perceived complexity. "Simple" tasks (commit, push, deploy) have caused the most severe framework violations because agents skip intake when they pattern-match a task as mechanical. The procedure is unconditional.
1. Define scope, constraints, and acceptance criteria.
2. Identify affected surfaces (API, DB, UI, infra, auth, CI/CD, docs).
3. **Deployment surface check (MANDATORY if task involves deploy, images, or containers):** Before ANY build or deploy action, check for CI/CD pipeline config (`.woodpecker/`, `.woodpecker.yml`, `.github/workflows/`). If pipelines exist, CI is the canonical build path — manual `docker build`/`docker push` is forbidden. Load `~/.config/mosaic/guides/CI-CD-PIPELINES.md` immediately.
4. Identify required guides and load them before implementation.
5. For code/API/auth/infra changes, load `~/.config/mosaic/guides/DOCUMENTATION.md`.
6. Determine budget constraints:
- if the user provided a plan limit or token budget, treat it as a HARD cap,
- if budget is unknown, derive a working budget from estimates and runtime limits, then continue autonomously.
7. Record budget assumptions and caps in the scratchpad before implementation starts.
8. Track estimated vs used tokens per logical unit and adapt strategy to remain inside budget.
9. If projected usage exceeds budget, auto-reduce scope/parallelism first; escalate only if cap still cannot be met.
## 2a. Steered Autonomy (Lights-Out)
1. Agent owns delivery end-to-end: planning, coding, testing, review, PR/repo operations, release/tag, and deployment (when in scope).
2. Human intervention is escalation-only; do not pause for routine approvals or handoffs.
3. Continue execution until completion criteria are met or an escalation trigger is hit.
## 3. Scratchpad Requirement
1. Create a task-specific scratchpad before implementation.
2. Record:
- objective
- plan
- progress checkpoints
- tests run
- risks/blockers
- final verification evidence
## 4. Embedded Execution Cycle (MANDATORY)
For implementation work, you MUST run this cycle in order:
1. `plan` - map PRD requirements to concrete implementation steps.
2. `code` - implement one logical unit.
3. `test` - run required baseline and situational checks for that unit.
4. `review` - perform independent code review on the current delta.
5. `remediate` - fix all findings and any test failures.
6. `review` - re-review remediated changes until blockers are cleared.
7. `commit` - commit only when the logical unit passes tests and review.
8. `pre-push queue guard` - before pushing, wait for running/queued project pipelines to clear: `~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose push`.
9. `push` - push immediately after queue guard passes.
10. `PR integration` - if external git provider is available, create/update PR to `main` and merge with required strategy via Mosaic wrappers.
11. `pre-merge queue guard` - before merging PR, wait for running/queued project pipelines to clear: `~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose merge`.
12. `CI/pipeline verification` - wait for terminal CI status and require green before completion (`~/.config/mosaic/tools/git/pr-ci-wait.sh` for PR-based workflow).
13. `issue closure` - close linked external issue (or close internal `docs/TASKS.md` task ref when provider is unavailable).
14. `greenfield situational test` - validate required user flows in a clean environment/startup path (post-merge for trunk workflow changes).
15. `deploy + post-deploy validation` - when deployment is in scope, deploy to configured target and run post-deploy health/smoke checks.
16. `repeat` - continue until all acceptance criteria are complete.
### Post-PR Hard Gate (Execute Sequentially, No Exceptions)
1. `~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose merge -B main`
2. `~/.config/mosaic/tools/git/pr-merge.sh -n <PR_NUMBER> -m squash`
3. `~/.config/mosaic/tools/git/pr-ci-wait.sh -n <PR_NUMBER>`
4. `~/.config/mosaic/tools/git/issue-close.sh -i <ISSUE_NUMBER>` (or close internal `docs/TASKS.md` ref when no provider exists)
5. If any step fails: set status `blocked`, report the exact failed wrapper command, and stop.
6. Do not ask the human to perform routine merge/close operations.
7. Do not claim completion before step 4 succeeds.
### Forbidden Anti-Patterns
**PR/Merge:**
1. Do NOT stop at "PR created" or "PR updated".
2. Do NOT ask "should I merge?" for routine delivery PRs.
3. Do NOT ask "should I close the issue?" after merge + green CI.
**Build/Deploy:** 4. Do NOT run `docker build` or `docker push` locally to deploy images when CI/CD pipelines exist in the repository. CI is the ONLY canonical build path. 5. Do NOT skip intake and surface identification because a task "seems simple." This is the #1 cause of framework violations. 6. Do NOT deploy without first verifying whether CI/CD pipelines exist (`.woodpecker/`, `.woodpecker.yml`, `.github/workflows/`). If they exist, use them. 7. If you are about to run `docker build` and have NOT loaded `ci-cd-pipelines.md`, STOP — you are violating the framework.
If any step fails, you MUST remediate and re-run from the relevant step before proceeding.
If push-queue/merge-queue/PR merge/CI/issue closure fails, status is `blocked` (not complete) and you MUST report the exact failed wrapper command.
## 5. Testing Priority Model
Use this order of priority:
1. Situational tests are the PRIMARY gate and MUST prove changed behavior meets requirements.
2. Baseline tests are REQUIRED safety checks and MUST run for all software changes.
3. TDD is risk-based and REQUIRED only for specific high-risk change types.
## 6. Mandatory Test Baseline
For all software changes, you MUST run baseline checks applicable to the repo/toolchain:
1. lint (or equivalent static checks)
2. type checks (if language/tooling supports it)
3. unit tests for changed logic
4. integration tests for changed boundaries
## 7. Situational Testing Matrix (PRIMARY GATE)
Run additional tests based on what changed:
| Change Surface | Required Situational Tests |
| ---------------------------- | ----------------------------------------------------------------------------- |
| Authentication/authorization | auth failure-path tests, permission boundary tests, token/session validation |
| Database schema/migrations | migration up/down validation, rollback safety, data integrity checks |
| API contract changes | backward compatibility checks, consumer-impact tests, contract tests |
| Frontend/UI workflow changes | end-to-end flow tests, accessibility sanity checks, state transition checks |
| CI/CD or deployment changes | pipeline execution validation, artifact integrity checks, rollback path check |
| Security-sensitive logic | abuse-case tests, input validation fuzzing/sanitization checks |
| Performance-critical path | baseline comparison, regression threshold checks |
## 8. Risk-Based TDD Requirement
TDD is REQUIRED for:
1. bug fixes (write a reproducer test first)
2. security/auth/permission logic changes
3. critical business logic and data-mutation rules
TDD is RECOMMENDED (not mandatory) for low-risk UI, copy, styling, and mechanical refactors.
If TDD is skipped for a non-required case, record the rationale in the scratchpad.
## 9. Mandatory Code Review Gate
If you modify source code, you MUST run an independent code review before completion.
1. Use automated review tooling when available.
2. If automated tooling is unavailable, run manual review using `~/.config/mosaic/guides/CODE-REVIEW.md`.
3. Any blocker or critical finding MUST be fixed or tracked as an explicit remediation task before closure.
## 10. Mandatory Documentation Gate
For code/API/auth/infra changes, documentation updates are REQUIRED before completion.
1. Apply the standard in `~/.config/mosaic/guides/DOCUMENTATION.md`.
2. Update required docs in the same logical change set as implementation.
3. Complete `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`.
4. If publish platform is unspecified, ask the user to choose in-app or external platform before publishing.
5. Missing required documentation is a BLOCKER.
## 11. Completion Gate (All Required)
You MUST satisfy all items before completion:
1. Acceptance criteria met.
2. Baseline tests passed.
3. Situational tests passed (primary gate), including required greenfield situational validation.
4. PRD is current and implementation is aligned with PRD.
5. Acceptance criteria mapped to verification evidence.
6. Code review completed for source code changes.
7. Required documentation updates completed and reviewed.
8. Scratchpad updated with evidence.
9. Known risks documented.
10. No unresolved blocker hidden.
11. If deployment is in scope, deployment target, release version, and post-deploy verification evidence are documented.
12. `docs/TASKS.md` status and issue/internal references are updated to match delivered work.
13. If source code changed and external provider is available: PR merged to `main` (squash), with merge evidence recorded.
14. CI/pipeline status is terminal green for the merged PR/head commit.
15. Linked external issue is closed (or internal task ref is closed when no provider exists).
16. If any of items 13-15 fail due access/tooling, report `blocked` with exact failed wrapper command and do not claim completion.
## 12. Review and Reporting
Completion report MUST include:
1. what changed
2. PRD alignment summary
3. acceptance criteria to evidence mapping
4. what was tested (baseline + situational)
5. what was reviewed (code review scope)
6. what documentation was updated
7. command-level evidence summary
8. residual risks
9. deployment and post-deploy verification summary (if in scope)
10. explicit pass/fail status
11. tracking summary (`docs/TASKS.md` updates and issue/internal refs)
12. PR lifecycle summary (PR number, merge commit, merge method)
13. CI/pipeline summary (run/check URL, terminal status)
14. issue closure summary (issue number/ref and close evidence)

View File

@@ -0,0 +1,91 @@
# Frontend Development Guide
## Before Starting
1. Check assigned issue in git repo: `~/.config/mosaic/tools/git/issue-list.sh -a @me`
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
3. Review existing components and patterns in the codebase
## Development Standards
### Framework Conventions
- Follow project's existing framework patterns (React, Vue, Svelte, etc.)
- Use existing component library/design system if present
- Maintain consistent file structure with existing code
### Styling
- Use project's established styling approach (CSS modules, Tailwind, styled-components, etc.)
- Follow existing naming conventions for CSS classes
- Ensure responsive design unless explicitly single-platform
### State Management
- Use project's existing state management solution
- Keep component state local when possible
- Document any new global state additions
### Accessibility
- Include proper ARIA labels
- Ensure keyboard navigation works
- Test with screen reader considerations
- Maintain color contrast ratios (WCAG 2.1 AA minimum)
## Testing Requirements (TDD)
1. Write tests BEFORE implementation
2. Minimum 85% coverage
3. Test categories:
- Unit tests for utility functions
- Component tests for UI behavior
- Integration tests for user flows
### Test Patterns
```javascript
// Component test example structure
describe('ComponentName', () => {
it('renders without crashing', () => {});
it('handles user interaction correctly', () => {});
it('displays error states appropriately', () => {});
it('is accessible', () => {});
});
```
## Code Style
- Follow Google JavaScript/TypeScript Style Guide
- **TypeScript: Follow `~/.config/mosaic/guides/TYPESCRIPT.md` — MANDATORY**
- Use ESLint/Prettier configuration from project
- Prefer functional components over class components (React)
- TypeScript strict mode is REQUIRED, not optional
### TypeScript Quick Rules (see TYPESCRIPT.md for full guide)
- **NO `any`** — define explicit types always
- **NO lazy `unknown`** — only for error catches and external data with validation
- **Explicit return types** on all exported functions
- **Explicit parameter types** always
- **Interface for props** — never inline object types
- **Event handlers** — use proper React event types
## Commit Format
```
feat(#123): Add user profile component
- Implement avatar display
- Add edit mode toggle
- Include form validation
Refs #123
```
## Before Completing
1. Run full test suite
2. Verify build succeeds
3. Update scratchpad with completion notes
4. Reference issue in commit: `Fixes #N` or `Refs #N`

View File

@@ -0,0 +1,339 @@
# Infrastructure & DevOps Guide
## Before Starting
1. Check assigned issue: `~/.config/mosaic/tools/git/issue-list.sh -a @me`
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
3. Review existing infrastructure configuration
## Vault Secrets Management
**CRITICAL**: Follow canonical Vault structure for ALL secrets.
### Structure
```
{mount}/{service}/{component}/{secret-name}
Examples:
- secret-prod/postgres/database/app
- secret-prod/redis/auth/default
- secret-prod/authentik/admin/token
```
### Environment Mounts
- `secret-dev/` - Development environment
- `secret-staging/` - Staging environment
- `secret-prod/` - Production environment
### Standard Field Names
- Credentials: `username`, `password`
- Tokens: `token`
- OAuth: `client_id`, `client_secret`
- Connection strings: `url`, `host`, `port`
See `docs/vault-secrets-structure.md` for complete reference.
## Container Standards
### Dockerfile Best Practices
```dockerfile
# Use specific version tags
FROM node:20-alpine
# Create non-root user
RUN addgroup -S app && adduser -S app -G app
# Set working directory
WORKDIR /app
# Copy dependency files first (layer caching)
COPY package*.json ./
RUN npm ci --only=production
# Copy application code
COPY --chown=app:app . .
# Switch to non-root user
USER app
# Use exec form for CMD
CMD ["node", "server.js"]
```
### Container Security
- Use minimal base images (alpine, distroless)
- Run as non-root user
- Don't store secrets in images
- Scan images for vulnerabilities
- Pin dependency versions
## Kubernetes/Docker Compose
### Resource Limits
Always set resource limits to prevent runaway containers:
```yaml
resources:
requests:
memory: '128Mi'
cpu: '100m'
limits:
memory: '256Mi'
cpu: '500m'
```
### Health Checks
```yaml
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
```
## CI/CD Pipelines
### Pipeline Stages
1. **Lint**: Code style and static analysis
2. **Test**: Unit and integration tests
3. **Build**: Compile and package
4. **Scan**: Security and vulnerability scanning
5. **Deploy**: Environment-specific deployment
### Pipeline Security
- Use secrets management (not hardcoded)
- Pin action/image versions
- Implement approval gates for production
- Audit pipeline access
## Steered-Autonomous Deployment (Hard Rule)
In lights-out mode, the agent owns deployment end-to-end when deployment is in scope.
The human is escalation-only for missing access, hard policy conflicts, or irreversible risk.
### Deployment Target Selection
1. Use explicit target from `docs/PRD.md` / `docs/PRD.json` or `docs/DEPLOYMENT.md`.
2. If unspecified, infer from existing project config/integration.
3. If multiple targets exist, choose the target already wired in CI/CD and document rationale.
### Supported Targets
- **Portainer**: Deploy via `~/.config/mosaic/tools/portainer/stack-redeploy.sh`, then verify with `stack-status.sh`.
- **Coolify**: Deploy via `~/.config/mosaic/tools/coolify/deploy.sh -u <uuid>`, then verify with `service-status.sh`.
- **Vercel**: Deploy via `vercel` CLI or connected Git integration, then verify preview/production URL health.
- **Other SaaS providers**: Use provider CLI/API/runbook with the same validation and rollback gates.
### Coolify API Operations
```bash
# List projects and services
~/.config/mosaic/tools/coolify/project-list.sh
~/.config/mosaic/tools/coolify/service-list.sh
# Check service status
~/.config/mosaic/tools/coolify/service-status.sh -u <uuid>
# Set env vars (takes effect on next deploy)
~/.config/mosaic/tools/coolify/env-set.sh -u <uuid> -k KEY -v VALUE
# Deploy
~/.config/mosaic/tools/coolify/deploy.sh -u <uuid>
```
**Known Coolify Limitations:**
- FQDN updates on compose sub-apps not supported via API (DB workaround required)
- Compose files must be base64-encoded in `docker_compose_raw` field
- Magic variables (`SERVICE_FQDN_*`) require list-style env syntax, not dict-style
- Rate limit: 200 requests per interval
### Cloudflare DNS Operations
Use the Cloudflare tools for any DNS configuration: pointing domains at services, adding TXT verification records, managing MX records, etc.
**Multi-instance support**: Credentials support named instances (e.g. `personal`, `work`). A `default` key in credentials.json determines which instance is used when `-a` is omitted. Pass `-a <instance>` to target a specific account.
```bash
# List all zones (domains) in the account
~/.config/mosaic/tools/cloudflare/zone-list.sh [-a instance]
# List DNS records for a zone (accepts zone name or ID)
~/.config/mosaic/tools/cloudflare/record-list.sh -z <zone> [-t type] [-n name]
# Create a DNS record
~/.config/mosaic/tools/cloudflare/record-create.sh -z <zone> -t <type> -n <name> -c <content> [-p] [-l ttl] [-P priority]
# Update a DNS record (requires record ID from record-list)
~/.config/mosaic/tools/cloudflare/record-update.sh -z <zone> -r <record-id> -t <type> -n <name> -c <content> [-p]
# Delete a DNS record
~/.config/mosaic/tools/cloudflare/record-delete.sh -z <zone> -r <record-id>
```
**Flag reference:**
| Flag | Purpose |
| ---- | ----------------------------------------------------------------------- |
| `-z` | Zone name (e.g. `mosaicstack.dev`) or 32-char zone ID |
| `-a` | Named Cloudflare instance (omit for default) |
| `-t` | Record type: `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `SRV`, etc. |
| `-n` | Record name: short (`app`) or FQDN (`app.example.com`) |
| `-c` | Record content/value (IP, hostname, TXT string, etc.) |
| `-r` | Record ID (from `record-list.sh` output) |
| `-p` | Enable Cloudflare proxy (orange cloud) — omit for DNS-only (grey cloud) |
| `-l` | TTL in seconds (default: `1` = auto) |
| `-P` | Priority for MX/SRV records |
| `-f` | Output format: `table` (default) or `json` |
**Common workflows:**
```bash
# Point a new subdomain at a server (proxied through Cloudflare)
~/.config/mosaic/tools/cloudflare/record-create.sh \
-z example.com -t A -n myapp -c 203.0.113.10 -p
# Add a TXT record for domain verification (never proxied)
~/.config/mosaic/tools/cloudflare/record-create.sh \
-z example.com -t TXT -n _verify -c "verification=abc123"
# Check what records exist before making changes
~/.config/mosaic/tools/cloudflare/record-list.sh -z example.com -t CNAME
# Update an existing record (get record ID from record-list first)
~/.config/mosaic/tools/cloudflare/record-update.sh \
-z example.com -r <record-id> -t A -n myapp -c 10.0.0.5 -p
```
**DNS + Deployment integration**: When deploying a new service via Coolify or Portainer that needs a public domain, the typical sequence is:
1. Create the DNS record pointing at the host IP (with `-p` for Cloudflare proxy if desired)
2. Deploy the service via Coolify/Portainer
3. Verify the domain resolves and the service is reachable
**Proxy (`-p`) guidance:**
- Use proxy (orange cloud) for web services — provides CDN, DDoS protection, and hides origin IP
- Skip proxy (grey cloud) for non-HTTP services (mail, SSH), wildcard records, or when the service handles its own TLS termination and needs direct client IP visibility
- Proxy is NOT compatible with non-standard ports outside Cloudflare's supported range
### Stack Health Check
Verify all infrastructure services are reachable:
```bash
~/.config/mosaic/tools/health/stack-health.sh
```
### Image Tagging and Promotion (Hard Rule)
For containerized deployments:
1. Build immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
2. Use mutable environment tags only as pointers: `testing`, optional `staging`, and `prod`.
3. Deploy by immutable digest, not by mutable tag alone.
4. Promote the exact tested digest between environments (no rebuild between testing and prod).
5. Do not use `latest` or `dev` as deployment references.
Blue-green is the default strategy for production promotion.
Canary is allowed only when automated SLO/error-rate gates and auto-rollback triggers are implemented.
### Post-Deploy Validation (REQUIRED)
1. Health endpoints return expected status.
2. Critical smoke tests pass in target environment.
3. Running version and digest match the promoted release candidate.
4. Observability signals (errors/latency) are within expected thresholds.
### Rollback Rule
If post-deploy validation fails:
1. Execute rollback/redeploy-safe path immediately.
2. Mark deployment as blocked in `docs/TASKS.md`.
3. Record failure evidence and next remediation step in scratchpad and release notes.
### Registry Retention and Cleanup
Cleanup MUST be automated.
- Keep all final release tags (`vX.Y.Z`) indefinitely.
- Keep active environment digests (`prod`, `testing`, and active blue/green slots).
- Keep recent RC tags (`vX.Y.Z-rc.N`) based on retention window.
- Remove stale `sha-*` and RC tags outside retention window if they are not actively deployed.
## Monitoring & Logging
### Logging Standards
- Use structured logging (JSON)
- Include correlation IDs
- Log at appropriate levels (ERROR, WARN, INFO, DEBUG)
- Never log sensitive data
### Metrics to Collect
- Request latency (p50, p95, p99)
- Error rates
- Resource utilization (CPU, memory)
- Business metrics
### Alerting
- Define SLOs (Service Level Objectives)
- Alert on symptoms, not causes
- Include runbook links in alerts
- Avoid alert fatigue
## Testing Infrastructure
### Test Categories
1. **Unit tests**: Terraform/Ansible logic
2. **Integration tests**: Deployed resources work together
3. **Smoke tests**: Critical paths after deployment
4. **Chaos tests**: Failure mode validation
### Infrastructure Testing Tools
- Terraform: `terraform validate`, `terraform plan`
- Ansible: `ansible-lint`, molecule
- Kubernetes: `kubectl dry-run`, kubeval
- General: Terratest, ServerSpec
## Commit Format
```
chore(#67): Configure Redis cluster
- Add Redis StatefulSet with 3 replicas
- Configure persistence with PVC
- Add Vault secret for auth password
Refs #67
```
## Before Completing
1. Validate configuration syntax
2. Run infrastructure tests
3. Test in dev/staging first
4. Document any manual steps required
5. Update scratchpad and close issue

View File

@@ -0,0 +1,51 @@
# Memory and Retention Rules
## Primary Memory Layer: OpenBrain
**OpenBrain is the canonical shared memory for all Mosaic agents across all harnesses and sessions.**
Use the `capture` MCP tool (or REST `POST /v1/thoughts`) to store:
- Discovered gotchas and workarounds
- Architectural decisions and rationale
- Project state and context for handoffs
- Anything a future agent should know
Use `search` or `recent` at session start to load prior context before acting.
This is not optional. An agent that uses local file-based memory instead of OpenBrain is a broken agent — its knowledge is invisible to every other agent on the platform.
## Hard Rules
1. Agent learnings MUST go to OpenBrain — not to any file-based memory location.
2. You MUST NOT write to runtime-native memory silos (they are write-blocked by hook).
3. Active execution state belongs in project `docs/` — not in memory files.
4. `~/.config/mosaic/memory/` is for mosaic framework technical notes only, not project knowledge.
## Runtime-Native Memory Silos (WRITE-BLOCKED)
These locations are blocked by PreToolUse hooks. Attempting to write there fails at the tool level.
| Runtime | Blocked silo | Use instead |
| ----------- | ---------------------------------- | ------------------- |
| Claude Code | `~/.claude/projects/*/memory/*.md` | OpenBrain `capture` |
| Codex | Runtime session memory | OpenBrain `capture` |
| OpenCode | Runtime session memory | OpenBrain `capture` |
MEMORY.md files may only contain behavioral guardrails that must be injected at load-path — not knowledge.
## Project Continuity Files (MANDATORY)
| File | Purpose | Location |
| -------------------------------- | ----------------------------------------- | --------------------------- |
| `docs/PRD.md` or `docs/PRD.json` | Source of requirements | Project `docs/` |
| `docs/TASKS.md` | Task tracking, milestones, issues, status | Project `docs/` |
| `docs/scratchpads/<task>.md` | Task-specific working memory | Project `docs/scratchpads/` |
| `AGENTS.md` | Project-local patterns and conventions | Project root |
## How the Block Works
`~/.config/mosaic/tools/qa/prevent-memory-write.sh` is registered as a `PreToolUse` hook in
`~/.claude/settings.json`. It intercepts Write/Edit/MultiEdit calls and rejects any targeting
`~/.claude/projects/*/memory/*.md` before the tool executes. Exit code 2 blocks the call and
the agent sees a message directing it to OpenBrain instead.

View File

@@ -0,0 +1,127 @@
# Orchestrator Learnings (Universal)
> Cross-project heuristic adjustments based on observed variance data.
>
> **Note:** This file contains generic patterns only. Project-specific evidence is stored in each project's `docs/tasks/orchestrator-learnings.json`.
## Task Type Multipliers
Apply these multipliers to base estimates from `ORCHESTRATOR.md`:
| Task Type | Base Estimate | Multiplier | Confidence | Samples | Last Updated |
| --------------------- | ---------------- | ---------- | ---------- | ------- | ------------ |
| STYLE_FIX | 3-5K | 0.64 | MEDIUM | n=1 | 2026-02-05 |
| BULK_CLEANUP | file_count × 550 | 1.0 | MEDIUM | n=2 | 2026-02-05 |
| GUARD_ADD | 5-8K | 1.0 | LOW | n=0 | - |
| SECURITY_FIX | 8-12K | 2.5 | LOW | n=0 | - |
| AUTH_ADD | 15-25K | 1.0 | HIGH | n=1 | 2026-02-05 |
| REFACTOR | 10-15K | 1.0 | LOW | n=0 | - |
| TEST_ADD | 15-25K | 1.0 | LOW | n=0 | - |
| ERROR_HANDLING | 8-12K | 2.3 | MEDIUM | n=1 | 2026-02-05 |
| CONFIG_DEFAULT_CHANGE | 5-10K | 1.8 | MEDIUM | n=1 | 2026-02-05 |
| INPUT_VALIDATION | 5-8K | 1.7 | MEDIUM | n=1 | 2026-02-05 |
## Phase Factors
Apply to all estimates based on task position in milestone:
| Phase Position | Factor | Rationale |
| ----------------- | ------ | -------------------------- |
| Early (tasks 1-3) | 1.45 | Codebase learning overhead |
| Mid (tasks 4-7) | 1.25 | Pattern recognition phase |
| Late (tasks 8+) | 1.10 | Established patterns |
## Estimation Formula
```
Final Estimate = Base Estimate × Type Multiplier × Phase Factor × TDD Overhead
Where:
- Base Estimate: From ORCHESTRATOR.md task type table
- Type Multiplier: From table above (default 1.0)
- Phase Factor: 1.45 / 1.25 / 1.10 based on position
- TDD Overhead: 1.20 if tests required
```
## Known Patterns
### BULK_CLEANUP
**Pattern:** Multi-file cleanup tasks are severely underestimated.
**Why:** Iterative testing across many files, cascading fixes, and debugging compound the effort.
**Observed:** +112% to +276% variance when using fixed estimates.
**Recommendation:** Use `file_count × 550` instead of fixed estimate.
### ERROR_HANDLING
**Pattern:** Error handling changes that modify type interfaces cascade through the codebase.
**Why:** Adding fields to result types requires updating all callers, error messages, and tests.
**Observed:** +131% variance.
**Multiplier:** 2.3x base estimate when type interfaces are modified.
### CONFIG_DEFAULT_CHANGE
**Pattern:** Config default changes require more test coverage than expected.
**Why:** Security-sensitive defaults need validation tests, warning tests, and edge case coverage.
**Observed:** +80% variance.
**Multiplier:** 1.8x when config changes need security validation.
### INPUT_VALIDATION
**Pattern:** Security input validation with allowlists is more complex than simple validation.
**Why:** Comprehensive allowlists (e.g., OAuth error codes), encoding requirements, and security tests add up.
**Observed:** +70% variance.
**Multiplier:** 1.7x when security allowlists are involved.
### STYLE_FIX
**Pattern:** Pure formatting fixes are faster than estimated when isolated.
**Observed:** -36% variance.
**Multiplier:** 0.64x for isolated style-only fixes.
## Changelog
| Date | Change | Samples | Confidence |
| ---------- | ------------------------------------------- | ------- | ---------- |
| 2026-02-05 | Added BULK_CLEANUP category | n=2 | MEDIUM |
| 2026-02-05 | Added STYLE_FIX multiplier 0.64 | n=1 | MEDIUM |
| 2026-02-05 | Confirmed AUTH_ADD heuristic accurate | n=1 | HIGH |
| 2026-02-05 | Added ERROR_HANDLING multiplier 2.3x | n=1 | MEDIUM |
| 2026-02-05 | Added CONFIG_DEFAULT_CHANGE multiplier 1.8x | n=1 | MEDIUM |
| 2026-02-05 | Added INPUT_VALIDATION multiplier 1.7x | n=1 | MEDIUM |
## Update Protocol
**Graduated Autonomy:**
| Phase | Condition | Action |
| ---------------------- | ----------------------------------------- | -------------------------------------------- |
| **Now** | All proposals | Human review required |
| **After 3 milestones** | <30% change, n≥3 samples, HIGH confidence | Auto-update allowed |
| **Mature** | All changes | Auto with notification, revert on regression |
**Validation Before Update:**
1. Minimum 3 samples for same task type
2. Standard deviation < 30% of mean
3. Outliers (>2σ) excluded
4. New formula must not increase variance on historical data
## Where to Find Project-Specific Data
- **Project learnings:** `<project>/docs/tasks/orchestrator-learnings.json`
- **Cross-project metrics:** `jarvis-brain/data/orchestrator-metrics.json`

View File

@@ -0,0 +1,268 @@
# Orchestrator Protocol — Mission Lifecycle Guide
> **Operational guide for agent sessions.** Distilled from the full specification at
> `jarvis-brain/docs/protocols/ORCHESTRATOR-PROTOCOL.md` (1,066 lines).
>
> Load this guide when: active mission detected, multi-milestone orchestration, mission continuation.
> Load `ORCHESTRATOR.md` for per-session execution protocol (planning, coding, review, commit cycle).
---
## 1. Relationship to ORCHESTRATOR.md
| Concern | Guide |
| -------------------------------------------------------------------- | ----------------- |
| How to execute within a session (plan, code, test, review, commit) | `ORCHESTRATOR.md` |
| How to manage a mission across sessions (resume, continue, handoff) | **This guide** |
| Both guides are active simultaneously during orchestration missions. |
---
## 2. Mission Manifest
**Location:** `docs/MISSION-MANIFEST.md`
**Owner:** Orchestrator (sole writer)
**Template:** `~/.config/mosaic/templates/docs/MISSION-MANIFEST.md.template`
The manifest is the persistent document tracking full mission scope, status, milestones, and session history. It survives session death.
### Update Rules
- Update **Phase** when transitioning (Intake → Planning → Execution → Continuation → Completion)
- Update **Current Milestone** when starting a new milestone
- Update **Progress** after each milestone completion
- Append to **Session History** at session start and end
- Update **Status** to `completed` only when ALL success criteria are verified
### Hard Rule
The manifest is the source of truth for mission scope. If the manifest says a milestone is done, it is done. If it says remaining, it remains.
---
## 3. Scratchpad Protocol
**Location:** `docs/scratchpads/{mission-id}.md`
**Template:** `~/.config/mosaic/templates/docs/mission-scratchpad.md.template`
### Rules
1. **First action** — Before ANY planning or coding, write the mission prompt to the scratchpad
2. **Append-only** — NEVER delete or overwrite previous entries
3. **Session log** — Record session start, tasks done, and outcome at session end
4. **Decisions** — Record all planning decisions with rationale
5. **Corrections** — Record course corrections from human or coordinator
6. **Never deleted** — Scratchpads survive mission completion (archival reference)
---
## 4. TASKS.md as Control Plane
**Location:** `docs/TASKS.md`
**Owner:** Orchestrator (sole writer). Workers read but NEVER modify.
### Table Schema
```markdown
| id | status | milestone | description | pr | notes |
```
### Status Values
`not-started``in-progress``done` (or `blocked` / `failed`)
### Planning Tasks Are First-Class
Include explicit planning tasks (e.g., `PLAN-001: Break down milestone into tasks`). These count toward progress.
### Post-Merge Tasks Are Explicit
Include verification tasks after merge: CI check, deployment verification, Playwright test. Don't assume they happen automatically.
---
## 5. Session Resume Protocol
When starting a session and an active mission is detected, follow this checklist:
### Detection (5-point check)
1. `docs/MISSION-MANIFEST.md` exists → read Phase, Current Milestone, Progress
2. `docs/scratchpads/*.md` exists → read latest scratchpad for decisions and corrections
3. `docs/TASKS.md` exists → read task state (what's done, what's next)
4. Git state → current branch, open PRs, recent commits
5. Provider state → open issues, milestone status (if accessible)
### Resume Procedure
1. Read the mission manifest FIRST
2. Read the scratchpad for session history and corrections
3. Read TASKS.md for current task state
4. Identify the next `not-started` or `in-progress` task
5. Continue execution from that task
6. Update Session History in the manifest
### Dirty State Recovery
| State | Recovery |
| ------------------------ | ------------------------------------------------------------------- |
| Dirty git working tree | Stash changes, log stash ref in scratchpad, resume clean |
| Open PR in bad state | Check PR status, close if broken, re-create if needed |
| Half-created issues | Audit issues against TASKS.md, reconcile |
| Tasks marked in-progress | Check if work was committed; if so, mark done; if not, restart task |
### Hard Rule
Session state is NEVER automatically deleted. The coordinator (human or automated) must explicitly request cleanup.
---
## 6. Mission Continuation
When a milestone completes and more milestones remain:
### Agent Handoff (at ~55-60% context)
If context usage is high, produce a handoff message:
1. Update TASKS.md with final task statuses
2. Update mission manifest with session results
3. Append session summary to scratchpad
4. Commit all state files
5. The coordinator will generate a continuation prompt for the next session
### Continuation Prompt and Capsule Format
The coordinator generates this (via `mosaic coord continue`) and writes a machine-readable capsule at `.mosaic/orchestrator/next-task.json`:
```
## Continuation Mission
Continue **{mission}** from existing state.
- Read docs/MISSION-MANIFEST.md for scope and status
- Read docs/scratchpads/{id}.md for decisions
- Read docs/TASKS.md for current state
- Continue from task {next-task-id}
```
### Between Sessions (r0 manual)
1. Agent stops (expected — this is the confirmed stamina limitation)
2. Human runs `mosaic coord mission` to check status
3. Human runs `mosaic coord continue` to generate continuation prompt
4. Human launches new session and pastes the prompt
5. New agent reads manifest, scratchpad, TASKS.md and continues
### Between Sessions (r0 assisted)
Use `mosaic coord run` to remove copy/paste steps:
1. Agent stops
2. Human runs `mosaic coord run [--claude|--codex]`
3. Coordinator regenerates continuation prompt + `next-task.json`
4. Coordinator launches selected runtime with scoped kickoff context
5. New session resumes from next task
---
## 7. Failure Taxonomy Quick Reference
| Code | Type | Recovery |
| ---- | ---------------------- | ----------------------------------------------------- |
| F1 | Premature Stop | Continuation prompt → new session (most common) |
| F2 | Context Exhaustion | Handoff message → new session |
| F3 | Session Crash | Check git state → `mosaic coord resume` → new session |
| F4 | Error Spiral | Kill session, mark task blocked, skip to next |
| F5 | Quality Gate Failure | Create QA remediation task |
| F6 | Infrastructure Failure | Pause, retry when service recovers |
| F7 | False Completion | Append correction to scratchpad, relaunch |
| F8 | Scope Drift | Kill session, relaunch with scratchpad ref |
| F9 | Subagent Failure | Orchestrator retries or creates remediation |
| F10 | Deadlock | Escalate to human |
### F1: Premature Stop — Detailed Recovery
This is the confirmed, most common failure. Every session will eventually trigger F1.
1. Session ends with tasks remaining in TASKS.md
2. Run `mosaic coord mission` — verify milestone status
3. If milestone complete: verify CI green, deployed, issues closed
4. Run `mosaic coord continue` — generates scoped continuation prompt
5. Launch new session, paste prompt
6. New session reads state and continues from next pending task
---
## 8. r0 Manual Coordinator Process
In r0, the Coordinator is Jason + shell scripts. No daemon. No automation.
### Commands
| Command | Purpose |
| --------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------ |
| `mosaic coord init --name "..." --milestones "..."` | Initialize a new mission |
| `mosaic coord mission` | Show mission progress dashboard |
| `mosaic coord status` | Check if agent session is still running |
| `mosaic coord continue` | Generate continuation prompt for next session |
| `mosaic coord run [--claude | --codex]` | Generate continuation context and launch runtime |
| `mosaic coord resume` | Crash recovery (detect dirty state, generate fix) |
| `mosaic coord resume --clean-lock` | Clear stale session lock after review |
### Typical Workflow
```
init → launch agent → [agent works] → agent stops →
status → mission → run → repeat
```
---
## 9. Operational Checklist
### Pre-Mission
- [ ] Mission initialized: `mosaic coord init`
- [ ] docs/MISSION-MANIFEST.md exists with scope and milestones
- [ ] docs/TASKS.md scaffolded
- [ ] docs/scratchpads/{id}.md scaffolded
- [ ] Success criteria defined in manifest
### Session Start
- [ ] Read manifest → know phase, milestone, progress
- [ ] Read scratchpad → know decisions, corrections, history
- [ ] Read TASKS.md → know what's done and what's next
- [ ] Write session start to scratchpad
- [ ] Update Session History in manifest
### Planning Gate (Hard Gate — No Coding Until Complete)
- [ ] Milestones created in provider (Gitea/GitHub)
- [ ] Issues created for all milestone tasks
- [ ] TASKS.md populated with all planned tasks (including planning + verification tasks)
- [ ] All planning artifacts committed and pushed
### Per-Task
- [ ] Update task status to `in-progress` in TASKS.md
- [ ] Execute task following ORCHESTRATOR.md cycle
- [ ] Update task status to `done` (or `blocked`/`failed`)
- [ ] Commit, push
### Milestone Completion
- [ ] All milestone tasks in TASKS.md are `done`
- [ ] CI/pipeline green
- [ ] PR merged to `main`
- [ ] Issues closed
- [ ] Update manifest: milestone status → completed
- [ ] Update scratchpad: session log entry
- [ ] If deployment target: verify accessible
### Mission Completion
- [ ] ALL milestones completed
- [ ] ALL success criteria verified with evidence
- [ ] manifest status → completed
- [ ] Final scratchpad entry with completion evidence
- [ ] Release tag created and pushed (if applicable)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
# PRD Requirement Guide (MANDATORY)
This guide defines how requirements are captured before coding.
## Hard Rules
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
2. The PRD is the authoritative requirements source for implementation and testing.
3. The main agent MUST prepare or update the PRD using user input and available project context before implementation starts.
4. The agent MUST NOT invent requirements silently.
5. In steered autonomy mode, best-guess decisions are REQUIRED when needed; each guessed decision MUST be marked with `ASSUMPTION:` and rationale.
## PRD Format
Allowed canonical formats:
1. `docs/PRD.md`
2. `docs/PRD.json`
Either format is valid. Both may exist if one is a transformed representation of the other.
For markdown PRDs, start from `~/.config/mosaic/templates/docs/PRD.md.template`.
## Best-Guess Mode
Steered autonomy is the default operating mode.
1. Agent SHOULD fill missing decisions in the PRD without waiting for routine confirmation.
2. Agent MUST mark each guessed decision with `ASSUMPTION:` and rationale.
3. If user explicitly requests strict-confirmation mode, the agent MUST ask before unresolved decisions are finalized.
4. For high-impact security/compliance/release uncertainty, escalate only if the decision cannot be safely constrained with rollback-ready defaults.
## Minimum PRD Content
Every PRD MUST include:
1. Problem statement and objective
2. In-scope and out-of-scope
3. User/stakeholder requirements
4. Functional requirements
5. Non-functional requirements (security, performance, reliability, observability)
6. Acceptance criteria
7. Constraints and dependencies
8. Risks and open questions
9. Testing and verification expectations
10. Delivery/milestone intent
## Pre-Coding Gate
Coding MUST NOT begin until:
1. PRD file exists (`docs/PRD.md` or `docs/PRD.json`)
2. PRD has required sections
3. Unresolved decisions are captured as explicit `ASSUMPTION:` entries with rationale and planned validation
## Change Control
When requirements materially change:
1. Update PRD first.
2. Then update implementation plan/tasks.
3. Then implement code changes.
Implementation that diverges from PRD without PRD updates is a blocker.

View File

@@ -0,0 +1,125 @@
# QA & Testing Guide
## Before Starting
1. Check assigned issue: `~/.config/mosaic/tools/git/issue-list.sh -a @me`
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
3. Review `docs/PRD.md` or `docs/PRD.json` as the requirements source.
4. Review acceptance criteria and affected change surfaces.
## Testing Policy (Hard Rules)
1. Situational testing is the PRIMARY validation gate.
2. Baseline testing is REQUIRED for all software changes.
3. TDD is risk-based and REQUIRED only for defined high-risk change types.
4. Tests MUST validate requirements and behavior, not only internal implementation details.
## Priority Order
1. Situational tests: prove requirements and real behavior on changed surfaces.
2. Baseline tests: lint/type/unit/integration safety checks.
3. TDD discipline: applied where risk justifies test-first workflow.
## Risk-Based TDD Requirement
| Change Type | TDD Requirement | Required Action |
| ---------------------------------------------- | --------------- | ---------------------------------------------------------------------- |
| Bug fix | REQUIRED | Write a failing reproducer test first, then fix. |
| Security/auth/permission logic | REQUIRED | Write failing security/permission-path test first. |
| Critical business logic or data mutation rules | REQUIRED | Write failing rule/invariant test first. |
| API behavior regression | REQUIRED | Write failing contract/behavior test first. |
| Low-risk UI copy/style/layout | OPTIONAL | Add verification tests as appropriate; TDD recommended, not mandatory. |
| Mechanical refactor with unchanged behavior | OPTIONAL | Ensure regression/smoke coverage and situational evidence. |
If TDD is not required and skipped, record rationale in scratchpad.
If TDD is required and skipped, task is NOT complete.
## Baseline Test Requirements
For all software changes, run baseline checks applicable to the repo:
1. lint/static checks
2. type checks
3. unit tests for changed logic
4. integration tests for changed boundaries
## Situational Testing Matrix (Primary Gate)
| Change Surface | Required Situational Tests |
| ---------------------------- | ----------------------------------------------------------------------------- |
| Authentication/authorization | auth failure-path tests, permission boundary tests, token/session validation |
| Database schema/migrations | migration up/down validation, rollback safety, data integrity checks |
| API contract changes | backward compatibility checks, consumer-impact tests, contract tests |
| Frontend/UI workflow changes | end-to-end flow tests, accessibility sanity checks, state transition checks |
| CI/CD or deployment changes | pipeline execution validation, artifact integrity checks, rollback path check |
| Security-sensitive logic | abuse-case tests, input validation fuzzing/sanitization checks |
| Performance-critical path | baseline comparison, regression threshold checks |
## Coverage Requirements
### Minimum Standards
- Overall Coverage: 85% minimum
- Critical Paths: 95% minimum (auth, payments, data mutations)
- New Code: 90% minimum
Coverage is necessary but NOT sufficient. Passing coverage does not replace situational verification.
## Requirements-to-Evidence Mapping (Mandatory)
Before completion, map each acceptance criterion to concrete evidence.
Acceptance criteria MUST come from the active PRD.
Template:
```markdown
| Acceptance Criterion | Verification Method | Evidence |
| -------------------- | ------------------------------------------------------ | ---------------- |
| AC-1: ... | Situational test / baseline test / manual verification | command + result |
| AC-2: ... | ... | ... |
```
## Browser Automation (Hard Rule)
All browser automation (Playwright, Cypress, Puppeteer) MUST run in **headless mode**.
Launching a visible browser collides with the user's display and active session.
- Playwright: use `headless: true` in config or `--headed` must NOT be passed
- Cypress: use `cypress run` (headless by default), never `cypress open`
- Puppeteer: use `headless: true` (default)
If a project's `playwright.config.ts` does not explicitly set `headless: true`, add it before running tests.
## Test Quality Rules
1. Test behavior and outcomes, not private implementation details.
2. Include failure-path and edge-case assertions for changed behavior.
3. Keep tests deterministic; no new flaky tests.
4. Keep tests isolated; no dependency on execution order.
## Anti-Gaming Rules
1. Do NOT stop at "tests pass" if acceptance criteria are not verified.
2. Do NOT write narrow tests that only satisfy assertions while missing real workflow behavior.
3. Do NOT claim completion without situational evidence for impacted surfaces.
## Reporting
QA report MUST include:
1. baseline tests run and outcomes
2. situational tests run and outcomes
3. TDD usage decision (required/applied or optional/skipped with rationale)
4. acceptance-criteria-to-evidence mapping
5. coverage results
6. residual risk notes
## Before Completing
1. Baseline tests pass.
2. Required situational tests pass.
3. TDD obligations met for required change types.
4. Acceptance criteria mapped to evidence.
5. No flaky tests introduced.
6. CI pipeline passes (if available).
7. Scratchpad updated with results.

View File

@@ -0,0 +1,440 @@
# TypeScript Style Guide
**Authority**: This guide is MANDATORY for all TypeScript code. No exceptions without explicit approval.
Based on Google TypeScript Style Guide with stricter enforcement.
---
## Core Principles
1. **Explicit over implicit** — Always declare types, never rely on inference for public APIs
2. **Specific over generic** — Use the narrowest type that works
3. **Safe over convenient** — Type safety is not negotiable
4. **Contract-first boundaries** — Cross-module and API payloads MUST use dedicated DTO files
---
## DTO Contract (MANDATORY)
DTO files are REQUIRED for TypeScript module boundaries to preserve shared context and consistency.
Hard requirements:
1. Input and output payloads crossing module boundaries MUST be defined in `*.dto.ts` files.
2. Controller/service boundary payloads MUST use DTO types; inline object literal types are NOT allowed.
3. Public API request/response contracts MUST use DTO files and remain stable across modules.
4. Shared DTOs used by multiple modules MUST live in a shared location (for example `src/shared/dto/` or `packages/shared/dto/`).
5. ORM/entity models MUST NOT be exposed directly across module boundaries; map them to DTOs.
6. DTO changes MUST be reflected in tests and documentation when contracts change.
```typescript
// ❌ WRONG: inline payload contract at boundary
export function createUser(payload: { email: string; role: string }): Promise<User> {}
// ✅ CORRECT: dedicated DTO file contract
// user-create.dto.ts
export interface UserCreateDto {
email: string;
role: UserRole;
}
// user-response.dto.ts
export interface UserResponseDto {
id: string;
email: string;
role: UserRole;
}
// service.ts
export function createUser(payload: UserCreateDto): Promise<UserResponseDto> {}
```
---
## Forbidden Patterns (NEVER USE)
### `any` Type — FORBIDDEN
```typescript
// ❌ NEVER
function process(data: any) {}
const result: any = fetchData();
Record<string, any>;
// ✅ ALWAYS define explicit types
interface UserData {
id: string;
name: string;
email: string;
}
function process(data: UserData) {}
```
### `unknown` as Lazy Typing — FORBIDDEN
`unknown` is only acceptable in these specific cases:
1. Error catch blocks (then immediately narrow)
2. JSON.parse results (then validate with Zod/schema)
3. External API responses before validation
```typescript
// ❌ NEVER - using unknown to avoid typing
function getData(): unknown {}
const config: Record<string, unknown> = {};
// ✅ ACCEPTABLE - error handling with immediate narrowing
try {
riskyOperation();
} catch (error: unknown) {
if (error instanceof Error) {
logger.error(error.message);
} else {
logger.error('Unknown error', { error: String(error) });
}
}
// ✅ ACCEPTABLE - external data with validation
const raw: unknown = JSON.parse(response);
const validated = UserSchema.parse(raw); // Zod validation
```
### Implicit `any` — FORBIDDEN
```typescript
// ❌ NEVER - implicit any from missing types
function process(data) {} // Parameter has implicit any
const handler = (e) => {}; // Parameter has implicit any
// ✅ ALWAYS - explicit types
function process(data: RequestPayload): ProcessedResult {}
const handler = (e: React.MouseEvent<HTMLButtonElement>): void => {};
```
### Type Assertions to Bypass Safety — FORBIDDEN
```typescript
// ❌ NEVER - lying to the compiler
const user = data as User;
const element = document.getElementById('app') as HTMLDivElement;
// ✅ USE - type guards and narrowing
function isUser(data: unknown): data is User {
return typeof data === 'object' && data !== null && 'id' in data;
}
if (isUser(data)) {
console.log(data.id); // Safe
}
// ✅ USE - null checks
const element = document.getElementById('app');
if (element instanceof HTMLDivElement) {
element.style.display = 'none'; // Safe
}
```
### Non-null Assertion (`!`) — FORBIDDEN (except tests)
```typescript
// ❌ NEVER in production code
const name = user!.name;
const element = document.getElementById('app')!;
// ✅ USE - proper null handling
const name = user?.name ?? 'Anonymous';
const element = document.getElementById('app');
if (element) {
// Safe to use element
}
```
---
## Required Patterns
### Explicit Return Types — REQUIRED for all public functions
```typescript
// ❌ WRONG - missing return type
export function calculateTotal(items: Item[]) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// ✅ CORRECT - explicit return type
export function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
```
### Explicit Parameter Types — REQUIRED always
```typescript
// ❌ WRONG
const multiply = (a, b) => a * b;
users.map((user) => user.name); // If user type isn't inferred
// ✅ CORRECT
const multiply = (a: number, b: number): number => a * b;
users.map((user: User): string => user.name);
```
### Interface Over Type Alias — PREFERRED for objects
```typescript
// ✅ PREFERRED - interface (extendable, better error messages)
interface User {
id: string;
name: string;
email: string;
}
// ✅ ACCEPTABLE - type alias for unions, intersections, primitives
type Status = 'active' | 'inactive' | 'pending';
type ID = string | number;
```
### Const Assertions for Literals — REQUIRED
```typescript
// ❌ WRONG - loses literal types
const config = {
endpoint: '/api/users',
method: 'GET',
};
// config.method is string, not 'GET'
// ✅ CORRECT - preserves literal types
const config = {
endpoint: '/api/users',
method: 'GET',
} as const;
// config.method is 'GET'
```
### Discriminated Unions — REQUIRED for variants
```typescript
// ❌ WRONG - optional properties for variants
interface ApiResponse {
success: boolean;
data?: User;
error?: string;
}
// ✅ CORRECT - discriminated union
interface SuccessResponse {
success: true;
data: User;
}
interface ErrorResponse {
success: false;
error: string;
}
type ApiResponse = SuccessResponse | ErrorResponse;
```
---
## Generic Constraints
### Meaningful Constraints — REQUIRED
```typescript
// ❌ WRONG - unconstrained generic
function merge<T>(a: T, b: T): T {}
// ✅ CORRECT - constrained generic
function merge<T extends object>(a: T, b: Partial<T>): T {}
```
### Default Generic Parameters — USE SPECIFIC TYPES
```typescript
// ❌ WRONG
interface Repository<T = unknown> {}
// ✅ CORRECT - no default if type should be explicit
interface Repository<T extends Entity> {}
// ✅ ACCEPTABLE - meaningful default
interface Cache<T extends Serializable = JsonValue> {}
```
---
## React/JSX Specific
### Event Handlers — EXPLICIT TYPES REQUIRED
```typescript
// ❌ WRONG
const handleClick = (e) => {};
const handleChange = (e) => {};
// ✅ CORRECT
const handleClick = (e: React.MouseEvent<HTMLButtonElement>): void => {};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {};
```
### Component Props — INTERFACE REQUIRED
```typescript
// ❌ WRONG - inline types
function Button({ label, onClick }: { label: string; onClick: () => void }) { }
// ✅ CORRECT - named interface
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
function Button({ label, onClick, disabled = false }: ButtonProps): JSX.Element {
return <button onClick={onClick} disabled={disabled}>{label}</button>;
}
```
### Children Prop — USE React.ReactNode
```typescript
interface LayoutProps {
children: React.ReactNode;
sidebar?: React.ReactNode;
}
```
---
## API Response Typing
### Define Explicit Response Types
```typescript
// ❌ WRONG
const response = await fetch('/api/users');
const data = await response.json(); // data is any
// ✅ CORRECT
interface UsersResponse {
users: User[];
pagination: PaginationInfo;
}
const response = await fetch('/api/users');
const data: UsersResponse = await response.json();
// ✅ BEST - with runtime validation
const response = await fetch('/api/users');
const raw = await response.json();
const data = UsersResponseSchema.parse(raw); // Zod validates at runtime
```
---
## Error Handling
### Typed Error Classes — REQUIRED for domain errors
```typescript
class ValidationError extends Error {
constructor(
message: string,
public readonly field: string,
public readonly code: string,
) {
super(message);
this.name = 'ValidationError';
}
}
class NotFoundError extends Error {
constructor(
public readonly resource: string,
public readonly id: string,
) {
super(`${resource} with id ${id} not found`);
this.name = 'NotFoundError';
}
}
```
### Error Narrowing — REQUIRED
```typescript
try {
await saveUser(user);
} catch (error: unknown) {
if (error instanceof ValidationError) {
return { error: error.message, field: error.field };
}
if (error instanceof NotFoundError) {
return { error: 'Not found', resource: error.resource };
}
if (error instanceof Error) {
logger.error('Unexpected error', { message: error.message, stack: error.stack });
return { error: 'Internal error' };
}
logger.error('Unknown error type', { error: String(error) });
return { error: 'Internal error' };
}
```
---
## ESLint Rules — ENFORCE THESE
```javascript
{
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/explicit-function-return-type": ["error", {
"allowExpressions": true,
"allowTypedFunctionExpressions": true
}],
"@typescript-eslint/explicit-module-boundary-types": "error",
"@typescript-eslint/no-inferrable-types": "off", // Allow explicit primitives
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/strict-boolean-expressions": "error",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-unsafe-member-access": "error",
"@typescript-eslint/no-unsafe-call": "error",
"@typescript-eslint/no-unsafe-return": "error"
}
```
---
## TSConfig Strict Mode — REQUIRED
```json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"useUnknownInCatchVariables": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true
}
}
```
---
## Summary: The Type Safety Hierarchy
From best to worst:
1. **Explicit specific type** (interface/type) — REQUIRED
2. **Generic with constraints** — ACCEPTABLE
3. **`unknown` with immediate validation** — ONLY for external data
4. **`any`** — FORBIDDEN
**When in doubt, define an interface.**

View File

@@ -0,0 +1,205 @@
# Vault Secrets Management Guide
This guide applies when the project uses HashiCorp Vault for secrets management.
## Before Starting
1. Verify Vault access: `vault status`
2. Authenticate: `vault login` (method depends on environment)
3. Check your permissions for the required paths
## Canonical Structure
**ALL Vault secrets MUST follow this structure:**
```
{mount}/{service}/{component}/{secret-name}
```
### Components
- **mount**: Environment-specific mount point
- **service**: The service or application name
- **component**: Logical grouping (database, api, oauth, etc.)
- **secret-name**: Specific secret identifier
## Environment Mounts
| Mount | Environment | Usage |
| ----------------- | ----------- | ---------------------- |
| `secret-dev/` | Development | Local dev, CI |
| `secret-staging/` | Staging | Pre-production testing |
| `secret-prod/` | Production | Live systems |
## Examples
```bash
# Database credentials
secret-prod/postgres/database/app
secret-prod/mysql/database/readonly
secret-staging/redis/auth/default
# API tokens
secret-prod/authentik/admin/token
secret-prod/stripe/api/live-key
secret-dev/sendgrid/api/test-key
# JWT/Authentication
secret-prod/backend-api/jwt/signing-key
secret-prod/auth-service/session/secret
# OAuth providers
secret-prod/backend-api/oauth/google
secret-prod/backend-api/oauth/github
# Internal services
secret-prod/loki/read-auth/admin
secret-prod/grafana/admin/password
```
## Standard Field Names
Use consistent field names within secrets:
| Purpose | Fields |
| ----------- | ---------------------------- |
| Credentials | `username`, `password` |
| Tokens | `token` |
| OAuth | `client_id`, `client_secret` |
| Connection | `url`, `host`, `port` |
| Keys | `public_key`, `private_key` |
### Example Secret Structure
```json
// secret-prod/postgres/database/app
{
"username": "app_user",
"password": "secure-password-here",
"host": "db.example.com",
"port": "5432",
"database": "myapp"
}
```
## Rules
1. **DO NOT GUESS** secret paths - Always verify the path exists
2. **Use helper scripts** in `scripts/vault/` when available
3. **All lowercase, hyphenated** (kebab-case) for all path segments
4. **Standard field names** - Use the conventions above
5. **No sensitive data in path names** - Path itself should not reveal secrets
6. **Environment separation** - Never reference prod secrets from dev
## Deprecated Paths (DO NOT USE)
These legacy patterns are deprecated and should be migrated:
| Deprecated | Migrate To |
| ------------------------- | ------------------------------------------- |
| `secret/infrastructure/*` | `secret-{env}/{service}/...` |
| `secret/oauth/*` | `secret-{env}/{service}/oauth/{provider}` |
| `secret/database/*` | `secret-{env}/{service}/database/{user}` |
| `secret/credentials/*` | `secret-{env}/{service}/{component}/{name}` |
## Reading Secrets
### CLI
```bash
# Read a secret
vault kv get secret-prod/postgres/database/app
# Get specific field
vault kv get -field=password secret-prod/postgres/database/app
# JSON output
vault kv get -format=json secret-prod/postgres/database/app
```
### Application Code
**Python (hvac):**
```python
import hvac
client = hvac.Client(url='https://vault.example.com')
secret = client.secrets.kv.v2.read_secret_version(
path='postgres/database/app',
mount_point='secret-prod'
)
password = secret['data']['data']['password']
```
**Node.js (node-vault):**
```javascript
const vault = require('node-vault')({ endpoint: 'https://vault.example.com' });
const secret = await vault.read('secret-prod/data/postgres/database/app');
const password = secret.data.data.password;
```
**Go:**
```go
secret, err := client.Logical().Read("secret-prod/data/postgres/database/app")
password := secret.Data["data"].(map[string]interface{})["password"].(string)
```
## Writing Secrets
Only authorized personnel should write secrets. If you need a new secret:
1. Request through proper channels (ticket, PR to IaC repo)
2. Follow the canonical structure
3. Document the secret's purpose
4. Set appropriate access policies
```bash
# Example (requires write permissions)
vault kv put secret-dev/myapp/database/app \
username="dev_user" \
password="dev-password" \
host="localhost" \
port="5432"
```
## Troubleshooting
### Permission Denied
```
Error: permission denied
```
- Verify your token has read access to the path
- Check if you're using the correct mount point
- Confirm the secret path exists
### Secret Not Found
```
Error: no value found at secret-prod/data/service/component/name
```
- Verify the exact path (use `vault kv list` to explore)
- Check for typos in service/component names
- Confirm you're using the correct environment mount
### Token Expired
```
Error: token expired
```
- Re-authenticate: `vault login`
- Check token TTL: `vault token lookup`
## Security Best Practices
1. **Least privilege** - Request only the permissions you need
2. **Short-lived tokens** - Use tokens with appropriate TTLs
3. **Audit logging** - All access is logged; act accordingly
4. **No local copies** - Don't store secrets in files or env vars long-term
5. **Rotate on compromise** - Immediately rotate any exposed secrets

View File

@@ -0,0 +1,231 @@
# Mosaic Bootstrap — Windows Installer
# PowerShell equivalent of install.sh
#
# Usage:
# powershell -ExecutionPolicy Bypass -File install.ps1
#
$ErrorActionPreference = "Stop"
$SourceDir = $PSScriptRoot
$TargetDir = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$InstallMode = if ($env:MOSAIC_INSTALL_MODE) { $env:MOSAIC_INSTALL_MODE.ToLowerInvariant() } else { "prompt" } # prompt|keep|overwrite
$PreservePaths = @("SOUL.md", "memory")
function Write-Ok { param([string]$Msg) Write-Host "" -ForegroundColor Green -NoNewline; Write-Host $Msg }
function Write-Warn { param([string]$Msg) Write-Host "" -ForegroundColor Yellow -NoNewline; Write-Host $Msg }
function Write-Fail { param([string]$Msg) Write-Host "" -ForegroundColor Red -NoNewline; Write-Host $Msg }
function Write-Step { param([string]$Msg) Write-Host ""; Write-Host $Msg -ForegroundColor White -BackgroundColor DarkGray }
function Test-ExistingInstall {
if (-not (Test-Path $TargetDir)) { return $false }
return (Test-Path (Join-Path $TargetDir "bin\mosaic")) -or (Test-Path (Join-Path $TargetDir "AGENTS.md")) -or (Test-Path (Join-Path $TargetDir "SOUL.md"))
}
function Select-InstallMode {
switch ($InstallMode) {
"prompt" { }
"keep" { return }
"overwrite" { return }
default {
Write-Fail "Invalid MOSAIC_INSTALL_MODE '$InstallMode'. Use: prompt, keep, overwrite."
exit 1
}
}
if (-not (Test-ExistingInstall)) {
$script:InstallMode = "overwrite"
return
}
if (-not [Environment]::UserInteractive) {
Write-Warn "Existing install detected without interactive input; defaulting to keep local files."
$script:InstallMode = "keep"
return
}
Write-Host ""
Write-Host "Existing Mosaic install detected at: $TargetDir"
Write-Host "Choose reinstall mode:"
Write-Host " 1) keep Keep local files (SOUL.md, memory/) while updating framework"
Write-Host " 2) overwrite Replace everything in $TargetDir"
Write-Host " 3) cancel Abort install"
$selection = Read-Host "Selection [1/2/3] (default: 1)"
$normalizedSelection = if ($null -eq $selection) { "" } else { $selection.ToLowerInvariant() }
switch ($normalizedSelection) {
"" { $script:InstallMode = "keep" }
"1" { $script:InstallMode = "keep" }
"k" { $script:InstallMode = "keep" }
"keep" { $script:InstallMode = "keep" }
"2" { $script:InstallMode = "overwrite" }
"o" { $script:InstallMode = "overwrite" }
"overwrite" { $script:InstallMode = "overwrite" }
"3" { Write-Fail "Install cancelled."; exit 1 }
"c" { Write-Fail "Install cancelled."; exit 1 }
"cancel" { Write-Fail "Install cancelled."; exit 1 }
default {
Write-Warn "Unrecognized selection '$selection'; defaulting to keep."
$script:InstallMode = "keep"
}
}
}
# ── Install framework ────────────────────────────────────────
Write-Step " Installing Mosaic framework "
if (-not (Test-Path $TargetDir)) { New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null }
Select-InstallMode
if ($InstallMode -eq "keep") {
Write-Ok "Install mode: keep local SOUL.md/memory while updating framework"
}
else {
Write-Ok "Install mode: overwrite existing files"
}
$preserveTmp = $null
if ($InstallMode -eq "keep") {
$preserveTmp = Join-Path ([System.IO.Path]::GetTempPath()) ("mosaic-preserve-" + [Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $preserveTmp -Force | Out-Null
foreach ($relPath in $PreservePaths) {
$src = Join-Path $TargetDir $relPath
if (Test-Path $src) {
$dstParent = Join-Path $preserveTmp (Split-Path $relPath -Parent)
if (-not [string]::IsNullOrEmpty($dstParent) -and -not (Test-Path $dstParent)) {
New-Item -ItemType Directory -Path $dstParent -Force | Out-Null
}
Copy-Item $src (Join-Path $preserveTmp $relPath) -Recurse -Force
}
}
}
Get-ChildItem $TargetDir -Exclude ".git" | Remove-Item -Recurse -Force
Get-ChildItem $SourceDir -Exclude ".git" | ForEach-Object {
$dest = Join-Path $TargetDir $_.Name
if ($_.PSIsContainer) {
Copy-Item $_.FullName $dest -Recurse -Force
}
else {
Copy-Item $_.FullName $dest -Force
}
}
if ($InstallMode -eq "keep" -and $null -ne $preserveTmp) {
foreach ($relPath in $PreservePaths) {
$src = Join-Path $preserveTmp $relPath
if (Test-Path $src) {
$dst = Join-Path $TargetDir $relPath
if (Test-Path $dst) {
Remove-Item $dst -Recurse -Force
}
$dstParent = Split-Path $dst -Parent
if (-not (Test-Path $dstParent)) {
New-Item -ItemType Directory -Path $dstParent -Force | Out-Null
}
Copy-Item $src $dst -Recurse -Force
}
}
Remove-Item -Path $preserveTmp -Recurse -Force -ErrorAction SilentlyContinue
}
Write-Ok "Framework installed to $TargetDir"
# ── Post-install tasks ───────────────────────────────────────
Write-Step " Post-install tasks "
$binDir = Join-Path $TargetDir "bin"
try {
& "$binDir\mosaic-link-runtime-assets.ps1" *>$null
Write-Ok "Runtime assets linked"
}
catch {
Write-Warn "Runtime asset linking failed (non-fatal)"
}
try {
& "$binDir\mosaic-ensure-sequential-thinking.ps1" *>$null
Write-Ok "sequential-thinking MCP configured"
}
catch {
if ($env:MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING -eq "1") {
Write-Warn "sequential-thinking MCP setup failed but bypassed (MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING=1)"
}
else {
Write-Fail "sequential-thinking MCP setup failed (hard requirement)."
Write-Fail "Set MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING=1 only for temporary bypass scenarios."
exit 1
}
}
if ($env:MOSAIC_SKIP_SKILLS_SYNC -eq "1") {
Write-Ok "Skills sync skipped (MOSAIC_SKIP_SKILLS_SYNC=1)"
}
else {
try {
& "$binDir\mosaic-sync-skills.ps1" *>$null
Write-Ok "Skills synced"
}
catch {
Write-Warn "Skills sync failed (non-fatal)"
}
}
try {
& "$binDir\mosaic-migrate-local-skills.ps1" -Apply *>$null
Write-Ok "Local skills migrated"
}
catch {
Write-Warn "Local skill migration failed (non-fatal)"
}
try {
& "$binDir\mosaic-doctor.ps1" *>$null
Write-Ok "Health audit passed"
}
catch {
Write-Warn "Health audit reported issues — run 'mosaic doctor' for details"
}
# ── PATH configuration ───────────────────────────────────────
Write-Step " PATH configuration "
$mosaicBin = Join-Path $TargetDir "bin"
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
$pathChanged = $false
if ($userPath -and $userPath.Split(";") -contains $mosaicBin) {
Write-Ok "Already in User PATH"
}
else {
$newPath = if ($userPath) { "$mosaicBin;$userPath" } else { $mosaicBin }
[Environment]::SetEnvironmentVariable("Path", $newPath, "User")
$env:Path = "$mosaicBin;$env:Path"
Write-Ok "Added to User PATH"
$pathChanged = $true
}
# ── Summary ──────────────────────────────────────────────────
Write-Host ""
Write-Host " Mosaic installed successfully." -ForegroundColor Green
Write-Host ""
$nextSteps = @()
if ($pathChanged) {
$nextSteps += "Open a new terminal (or log out and back in) to activate PATH."
}
$soulPath = Join-Path $TargetDir "SOUL.md"
if (-not (Test-Path $soulPath)) {
$nextSteps += "Run 'mosaic init' to set up your agent identity (SOUL.md)."
}
if ($nextSteps.Count -gt 0) {
Write-Host " Next steps:" -ForegroundColor White
for ($i = 0; $i -lt $nextSteps.Count; $i++) {
Write-Host " $($i + 1). " -NoNewline
Write-Host $nextSteps[$i] -ForegroundColor Cyan
}
Write-Host ""
}

View File

@@ -0,0 +1,22 @@
# Mosaic Profiles
Profiles are runtime-neutral context packs that can be consumed by any agent runtime.
## Layout
- `domains/`: regulated-domain and security context (HIPAA, fintech, crypto, etc.)
- `tech-stacks/`: stack-specific conventions and quality checks
- `workflows/`: reusable execution workflows
## Runtime Split
- Runtime-neutral content belongs here under `~/.config/mosaic/profiles`.
- Runtime-specific settings belong under `~/.config/mosaic/runtime/<runtime>/...`.
Current runtime overlay example:
- `~/.config/mosaic/runtime/claude/settings-overlays/jarvis-loop.json`
## Claude Compatibility
`mosaic-link-runtime-assets` prunes legacy preset symlink trees from `~/.claude` so Mosaic remains canonical and Claude uses runtime overlays that reference Mosaic paths directly.

View File

@@ -0,0 +1,190 @@
{
"name": "Cryptocurrency & Web3 Security",
"description": "Security patterns for blockchain, cryptocurrency, and Web3 applications",
"domainKeywords": [
"crypto",
"blockchain",
"web3",
"defi",
"nft",
"wallet",
"smart contract",
"ethereum"
],
"compliance": {
"regulations": ["AML", "KYC", "FATF", "BSA", "Regional crypto regulations"],
"scope": "Applications handling cryptocurrencies and digital assets",
"requirements": [
"Secure private key management",
"Anti-money laundering (AML) compliance",
"Know Your Customer (KYC) verification",
"Transaction monitoring and reporting",
"Wallet security and multi-signature",
"Smart contract security audits"
]
},
"securityPatterns": {
"walletSecurity": {
"privateKeys": "Never store private keys in plaintext",
"keyDerivation": "Use BIP32/BIP44 for key derivation",
"storage": "Hardware Security Modules (HSMs) for production",
"backup": "Secure backup and recovery procedures",
"multiSig": "Multi-signature wallets for high-value transactions"
},
"smartContracts": {
"auditing": "Professional security audits required",
"testing": "Comprehensive test coverage including edge cases",
"upgradeability": "Consider proxy patterns for upgradeable contracts",
"accessControl": "Role-based access control in contracts",
"gasOptimization": "Optimize for gas efficiency and DoS protection"
},
"transactionSecurity": {
"validation": "Multi-layer transaction validation",
"monitoring": "Real-time transaction monitoring",
"limits": "Configurable transaction limits",
"timelock": "Time-delayed execution for large transactions",
"approval": "Multi-party approval workflows"
},
"apiSecurity": {
"authentication": "Strong API authentication (JWT + API keys)",
"rateLimit": "Aggressive rate limiting for trading APIs",
"signing": "Request signing for sensitive operations",
"websockets": "Secure WebSocket connections for real-time data"
}
},
"implementationPatterns": {
"backend": {
"walletIntegration": {
"abstraction": "Abstract wallet operations behind service layer",
"keyManagement": "Separate key management from application logic",
"transactions": "Queue and batch transactions for efficiency",
"monitoring": "Monitor blockchain for transaction confirmations"
},
"tradingEngine": {
"orderMatching": "Secure order matching algorithms",
"balanceTracking": "Accurate balance tracking with locks",
"riskManagement": "Position limits and risk controls",
"latency": "Low-latency execution for competitive trading"
},
"compliance": {
"kyc": "Identity verification workflows",
"aml": "Automated AML screening and monitoring",
"reporting": "Suspicious activity reporting (SAR)",
"sanctions": "OFAC and sanctions list screening"
}
},
"frontend": {
"walletConnection": {
"webWallets": "Support for MetaMask, WalletConnect, etc.",
"security": "Validate wallet signatures and addresses",
"persistence": "Secure session management",
"switching": "Handle network and account switching"
},
"trading": {
"realTime": "Real-time price and order book updates",
"charting": "Advanced charting capabilities",
"orderTypes": "Support for various order types",
"riskWarnings": "Clear risk disclosures and warnings"
}
}
},
"blockchainIntegration": {
"ethereum": {
"web3": "Use ethers.js or web3.js for blockchain interaction",
"infura": "Reliable node access via Infura/Alchemy",
"events": "Event listening and log parsing",
"gasManagement": "Dynamic gas price management"
},
"bitcoin": {
"addresses": "Support for multiple address types",
"utxo": "UTXO management and coin selection",
"fees": "Dynamic fee estimation",
"scripting": "Advanced scripting for complex transactions"
},
"multiChain": {
"abstraction": "Chain-agnostic service interfaces",
"bridging": "Cross-chain bridge integrations",
"networks": "Support for testnets and multiple networks",
"consensus": "Handle different consensus mechanisms"
}
},
"testingRequirements": {
"coverage": {
"minimum": "95% for financial logic modules",
"focus": "Security-critical components and edge cases"
},
"security": [
"Smart contract security audits",
"Penetration testing for web interfaces",
"Key management security testing",
"Transaction flow security validation",
"API security testing"
],
"blockchain": [
"Test on multiple networks (mainnet, testnet)",
"Handle network congestion scenarios",
"Test transaction failure and retry logic",
"Validate gas estimation accuracy",
"Test blockchain reorganization handling"
]
},
"context7Libraries": [
"ethers",
"web3",
"@metamask/providers",
"bitcoinjs-lib",
"@walletconnect/client",
"bip32",
"bip39"
],
"codeTemplates": {
"walletService": {
"description": "Secure wallet service interface",
"template": "@Injectable()\nexport class WalletService {\n async signTransaction(transaction: Transaction, keyId: string): Promise<string> {\n const privateKey = await this.keyManager.getKey(keyId);\n return this.signer.sign(transaction, privateKey);\n }\n\n async validateAddress(address: string, network: Network): Promise<boolean> {\n return this.validator.isValid(address, network);\n }\n}"
},
"transactionMonitor": {
"description": "Blockchain transaction monitoring",
"template": "this.web3.eth.subscribe('pendingTransactions', (txHash) => {\n this.web3.eth.getTransaction(txHash).then(tx => {\n if (this.isWatchedAddress(tx.to)) {\n this.processIncomingTransaction(tx);\n }\n });\n});"
},
"smartContractInteraction": {
"description": "Safe smart contract interaction",
"template": "const contract = new ethers.Contract(address, abi, signer);\nconst gasEstimate = await contract.estimateGas.transfer(to, amount);\nconst tx = await contract.transfer(to, amount, {\n gasLimit: gasEstimate.mul(110).div(100), // 10% buffer\n gasPrice: await this.getOptimalGasPrice()\n});"
}
},
"complianceChecklist": [
"Know Your Customer (KYC) procedures implemented",
"Anti-Money Laundering (AML) monitoring in place",
"Suspicious activity reporting (SAR) procedures",
"OFAC and sanctions screening implemented",
"Transaction monitoring and analysis tools",
"Customer due diligence (CDD) procedures",
"Enhanced due diligence (EDD) for high-risk customers",
"Record keeping and data retention policies",
"Compliance training for staff",
"Regular compliance audits and reviews"
],
"securityBestPractices": [
"Never store private keys in application code",
"Use hardware security modules (HSMs) for key storage",
"Implement multi-signature wallets for treasury management",
"Conduct regular security audits of smart contracts",
"Use time-locked transactions for large amounts",
"Implement comprehensive transaction monitoring",
"Use secure random number generation",
"Validate all blockchain data independently",
"Implement proper access controls and authentication",
"Maintain detailed audit logs of all operations"
],
"riskAssessment": [
"Private key compromise and theft",
"Smart contract vulnerabilities and exploits",
"Exchange hacks and loss of user funds",
"Regulatory compliance failures",
"Market manipulation and fraud",
"Technical failures and system outages",
"Insider threats and malicious employees",
"Third-party service provider risks",
"Quantum computing threats to cryptography",
"Cross-chain bridge vulnerabilities"
]
}

View File

@@ -0,0 +1,190 @@
{
"name": "Fintech Security Compliance",
"description": "PCI DSS and financial security requirements for fintech applications",
"domainKeywords": [
"payment",
"financial",
"banking",
"credit",
"debit",
"transaction",
"pci",
"fintech"
],
"compliance": {
"regulations": ["PCI DSS", "PSD2", "SOX", "KYC", "AML"],
"scope": "Applications processing payment card data",
"requirements": [
"Secure cardholder data",
"Encrypt transmission of cardholder data",
"Protect stored cardholder data",
"Maintain vulnerability management program",
"Implement strong access control measures",
"Regularly monitor and test networks",
"Maintain information security policy"
]
},
"dataClassification": {
"pan": {
"definition": "Primary Account Number (Credit/Debit card number)",
"storage": "Never store full PAN unless absolutely necessary",
"masking": "Show only last 4 digits",
"encryption": "AES-256 if storage required",
"transmission": "Always encrypted with TLS 1.2+"
},
"sadData": {
"definition": "Sensitive Authentication Data",
"types": ["CVV2", "PIN", "Track data"],
"storage": "Never store SAD after authorization",
"handling": "Process but do not retain"
},
"cardholderData": {
"definition": "PAN + cardholder name, service code, expiration date",
"minimization": "Store only if business need exists",
"retention": "Purge when no longer needed",
"access": "Restrict access to authorized personnel only"
}
},
"securityPatterns": {
"encryption": {
"algorithm": "AES-256 for data at rest",
"keyManagement": "Hardware Security Modules (HSMs) preferred",
"transmission": "TLS 1.2+ for data in transit",
"tokenization": "Replace PAN with non-sensitive tokens"
},
"authentication": {
"mfa": "Multi-factor authentication mandatory",
"passwordPolicy": "Complex passwords, regular rotation",
"sessionManagement": "Secure session handling with timeout",
"biometric": "Support for biometric authentication"
},
"authorization": {
"rbac": "Role-based access control",
"segregationOfDuties": "Separate roles for sensitive operations",
"leastPrivilege": "Minimum necessary access principle",
"approval": "Multi-person approval for high-value transactions"
},
"fraudPrevention": {
"riskScoring": "Real-time transaction risk assessment",
"monitoring": "Anomaly detection and behavioral analytics",
"alerts": "Immediate alerts for suspicious activities",
"blocking": "Automatic blocking of fraudulent transactions"
}
},
"implementationPatterns": {
"backend": {
"paymentProcessing": {
"tokenization": "Use payment tokens instead of card data",
"validation": "Validate all payment inputs",
"logging": "Log transactions without sensitive data",
"encryption": "Encrypt cardholder data before storage"
},
"apiSecurity": {
"rateLimit": "Implement rate limiting",
"apiKeys": "Secure API key management",
"signing": "Request signing for sensitive operations",
"monitoring": "Monitor API usage patterns"
},
"database": {
"encryption": "Database-level encryption for sensitive fields",
"access": "Database access controls and monitoring",
"backup": "Encrypted backups with secure key management",
"masking": "Data masking for non-production environments"
}
},
"frontend": {
"paymentForms": {
"https": "Always use HTTPS for payment pages",
"validation": "Client-side validation with server confirmation",
"autocomplete": "Disable autocomplete for sensitive fields",
"iframes": "Use secure iframes for payment card input"
},
"dataHandling": {
"noStorage": "Never store payment data in browser",
"masking": "Mask card numbers in UI",
"timeout": "Session timeout for payment pages",
"clearData": "Clear payment data from memory after use"
}
}
},
"testingRequirements": {
"coverage": {
"minimum": "90% for payment processing modules",
"focus": "Security controls and fraud prevention"
},
"security": [
"Penetration testing quarterly",
"Vulnerability scanning monthly",
"Code review for all payment code",
"Test encryption implementation",
"Validate tokenization process"
],
"compliance": [
"PCI DSS compliance validation",
"Test access controls",
"Validate audit logging",
"Test incident response procedures",
"Verify data retention policies"
]
},
"context7Libraries": [
"stripe",
"bcrypt",
"jsonwebtoken",
"helmet",
"express-rate-limit",
"crypto"
],
"codeTemplates": {
"paymentEntity": {
"description": "Payment entity with tokenization",
"template": "@Entity()\nexport class Payment {\n @Tokenized()\n @Column()\n cardToken: string;\n\n @Column()\n lastFourDigits: string;\n\n @Encrypted()\n @Column()\n amount: number;\n}"
},
"transactionLog": {
"description": "Secure transaction logging",
"template": "await this.auditService.logTransaction({\n transactionId: transaction.id,\n userId: user.id,\n amount: transaction.amount,\n currency: transaction.currency,\n status: 'COMPLETED',\n riskScore: riskAssessment.score,\n timestamp: new Date()\n});"
},
"fraudCheck": {
"description": "Fraud prevention check",
"template": "const riskScore = await this.fraudService.assessRisk({\n userId: user.id,\n amount: transaction.amount,\n location: transaction.location,\n deviceFingerprint: request.deviceId\n});\n\nif (riskScore > FRAUD_THRESHOLD) {\n await this.alertService.triggerFraudAlert(transaction);\n}"
}
},
"complianceChecklist": [
"Cardholder data is encrypted at rest and in transit",
"Sensitive authentication data is not stored",
"Access to cardholder data is restricted and monitored",
"Strong cryptography and security protocols are used",
"Antivirus software is maintained",
"Secure systems and applications are developed",
"Access to data is restricted by business need-to-know",
"Unique IDs are assigned to each person with computer access",
"Physical access to cardholder data is restricted",
"All access to network resources is logged and monitored",
"Security systems and processes are regularly tested",
"Information security policy is maintained"
],
"riskAssessment": [
"Unauthorized access to payment data",
"Data breaches and card data theft",
"Fraud and unauthorized transactions",
"System vulnerabilities and exploits",
"Insider threats and malicious employees",
"Third-party payment processor risks",
"Network security vulnerabilities",
"Application security weaknesses",
"Physical security of payment systems",
"Business continuity and disaster recovery"
],
"regulatoryReporting": [
"PCI DSS compliance reports",
"Suspicious activity reports (SARs)",
"Currency transaction reports (CTRs)",
"Know Your Customer (KYC) documentation",
"Anti-Money Laundering (AML) compliance",
"Data breach notification requirements",
"Consumer privacy disclosures",
"Financial audit requirements",
"Incident response documentation",
"Third-party risk assessments"
]
}

View File

@@ -0,0 +1,189 @@
{
"name": "Healthcare HIPAA Compliance",
"description": "HIPAA compliance requirements for healthcare applications handling PHI",
"domainKeywords": ["health", "medical", "patient", "hipaa", "phi", "healthcare"],
"compliance": {
"regulation": "HIPAA (Health Insurance Portability and Accountability Act)",
"scope": "All applications handling Protected Health Information (PHI)",
"requirements": [
"Encrypt PHI at rest and in transit",
"Implement access controls for PHI",
"Audit all access to PHI",
"Ensure data integrity",
"Implement proper user authentication",
"Maintain data minimization practices"
]
},
"dataClassification": {
"phi": {
"definition": "Individually identifiable health information",
"examples": [
"Names, addresses, birth dates",
"Phone numbers, email addresses",
"Social Security numbers",
"Medical record numbers",
"Health plan beneficiary numbers",
"Account numbers",
"Certificate/license numbers",
"Vehicle identifiers and serial numbers",
"Device identifiers and serial numbers",
"Web Universal Resource Locators (URLs)",
"Internet Protocol (IP) address numbers",
"Biometric identifiers",
"Full face photographic images",
"Medical diagnoses and treatment information",
"Lab results and vital signs"
],
"encryption": "AES-256 encryption required",
"storage": "Must be encrypted at rest",
"transmission": "Must be encrypted in transit (TLS 1.2+)"
}
},
"securityPatterns": {
"encryption": {
"algorithm": "AES-256",
"keyManagement": "Use AWS KMS, Azure Key Vault, or similar",
"implementation": "Field-level encryption for PHI columns",
"example": "@Encrypted decorator for entity fields"
},
"authentication": {
"method": "Multi-factor authentication required",
"tokenType": "JWT with refresh tokens",
"sessionTimeout": "Maximum 15 minutes inactive timeout",
"passwordPolicy": "Minimum 8 characters, complexity requirements"
},
"authorization": {
"model": "Role-Based Access Control (RBAC)",
"principle": "Minimum necessary access",
"implementation": "Care group permissions with data segmentation",
"auditTrail": "Log all authorization decisions"
},
"auditLogging": {
"requirement": "All PHI access must be logged",
"fields": [
"User ID",
"Patient ID",
"Action performed",
"Timestamp",
"IP address",
"Success/failure",
"Data accessed"
],
"retention": "6 years minimum",
"integrity": "Logs must be tamper-evident"
}
},
"implementationPatterns": {
"backend": {
"entities": {
"phiFields": "Mark PHI fields with @PHIEncrypted decorator",
"auditables": "Extend BaseAuditableEntity for PHI entities",
"relationships": "Implement proper access control on relationships"
},
"controllers": {
"authentication": "All PHI endpoints require authentication",
"authorization": "Check user permissions before PHI access",
"logging": "Log all PHI access attempts",
"validation": "Validate all inputs to prevent injection"
},
"services": {
"encryption": "Encrypt PHI before database storage",
"decryption": "Decrypt PHI only for authorized access",
"minimization": "Return only necessary PHI fields",
"auditing": "Create audit log entries for all PHI operations"
}
},
"frontend": {
"dataHandling": {
"localStorage": "Never store PHI in localStorage",
"sessionStorage": "Only encrypted session data allowed",
"memory": "Clear PHI from component state on unmount",
"logging": "Never log PHI to console or external services"
},
"ui": {
"masking": "Mask sensitive data by default",
"permissions": "Hide UI elements based on user roles",
"timeout": "Implement session timeout with warnings",
"accessibility": "Ensure screen readers don't expose PHI inappropriately"
}
}
},
"testingRequirements": {
"coverage": {
"minimum": "80% for all PHI-handling modules",
"focus": "Security and privacy controls"
},
"security": [
"Test for PHI leakage in API responses",
"Verify encryption of PHI fields",
"Test authorization controls",
"Validate audit logging functionality",
"Test session timeout behavior"
],
"compliance": [
"Verify minimum necessary access",
"Test audit log completeness",
"Validate encryption implementation",
"Test user access controls",
"Verify data retention policies"
]
},
"context7Libraries": [
"@nestjs/jwt",
"bcrypt",
"helmet",
"crypto",
"jsonwebtoken",
"express-rate-limit"
],
"codeTemplates": {
"phiEntity": {
"description": "Entity with PHI fields",
"template": "@Entity()\nexport class Patient {\n @PHIEncrypted()\n @Column()\n firstName: string;\n\n @AuditableField()\n @Column()\n medicalRecordNumber: string;\n}"
},
"auditLog": {
"description": "Audit log entry",
"template": "await this.auditService.log({\n userId: user.id,\n action: 'VIEW_PATIENT',\n resourceType: 'Patient',\n resourceId: patientId,\n ipAddress: request.ip,\n timestamp: new Date()\n});"
},
"authGuard": {
"description": "HIPAA auth guard",
"template": "@UseGuards(JwtAuthGuard, RolesGuard)\n@RequirePermission('view_patient_phi')\n@ApiSecurity('bearer')"
}
},
"complianceChecklist": [
"All PHI fields are encrypted at rest",
"All PHI transmission uses TLS 1.2+",
"User authentication is implemented with MFA",
"Role-based access control is enforced",
"All PHI access is logged and auditable",
"Session timeout is configured (max 15 minutes)",
"Password policies meet HIPAA requirements",
"Data backup and recovery procedures are secure",
"Incident response procedures are documented",
"Employee access is based on minimum necessary principle"
],
"riskAssessment": [
"Unauthorized access to PHI",
"Data breaches due to weak encryption",
"Insider threats and inappropriate access",
"Data loss due to inadequate backups",
"System vulnerabilities and exploits",
"Third-party vendor security risks",
"Physical security of systems and data",
"Network security and access controls",
"Application security vulnerabilities",
"Business continuity and disaster recovery"
],
"incidentResponse": [
"Identify and contain the incident",
"Assess the scope and severity",
"Notify affected individuals if required",
"Report to HHS if breach affects 500+ individuals",
"Implement corrective actions",
"Document all incident response activities",
"Conduct post-incident review and lessons learned",
"Update security policies and procedures",
"Provide additional training if needed",
"Monitor for similar incidents"
]
}

View File

@@ -0,0 +1,154 @@
{
"name": "NestJS Backend",
"description": "NestJS backend with TypeORM, PostgreSQL, and comprehensive testing",
"filePatterns": ["*.ts", "*.js"],
"excludePatterns": ["*.spec.ts", "*.test.ts", "*.d.ts"],
"techStack": {
"framework": "NestJS",
"language": "TypeScript",
"database": "TypeORM + PostgreSQL",
"validation": "class-validator + class-transformer",
"testing": "Jest + Supertest",
"documentation": "Swagger/OpenAPI",
"caching": "Redis + cache-manager",
"queues": "Bull + Redis"
},
"conventions": {
"naming": {
"variables": "camelCase",
"functions": "camelCase",
"classes": "PascalCase",
"interfaces": "PascalCase with I prefix",
"types": "PascalCase with T prefix",
"enums": "PascalCase",
"constants": "UPPER_SNAKE_CASE"
},
"fileStructure": {
"modules": "Feature-based modules in src/{feature}/",
"controllers": "{feature}.controller.ts",
"services": "{feature}.service.ts",
"entities": "{feature}.entity.ts",
"dtos": "dto/{feature}.dto.ts",
"tests": "{feature}.controller.spec.ts, {feature}.service.spec.ts"
},
"imports": {
"style": "Absolute imports with @ prefix when available",
"grouping": "Third-party, @nestjs, internal, relative",
"sorting": "Alphabetical within groups"
}
},
"qualityChecks": {
"lint": {
"command": "npx eslint --fix",
"config": "Google TypeScript ESLint config",
"autoFix": true
},
"format": {
"command": "npx prettier --write",
"config": "80 character line limit",
"autoFix": true
},
"build": {
"command": "npm run build",
"checkTypes": true,
"failOnError": true
},
"test": {
"unit": "npm run test:unit",
"integration": "npm run test:integration",
"coverage": "npm run test:cov",
"minimumCoverage": 40
}
},
"codePatterns": {
"controller": {
"decorators": ["@Controller", "@ApiTags", "@UseGuards"],
"methods": ["@Get", "@Post", "@Put", "@Delete", "@Patch"],
"responses": ["@ApiResponse", "@ApiOperation"],
"validation": ["@Body", "@Param", "@Query with DTOs"],
"errorHandling": "Use HttpException and custom exception filters"
},
"service": {
"injection": "Constructor dependency injection with @Injectable",
"methods": "Async methods with proper error handling",
"database": "Use TypeORM repository pattern",
"transactions": "@Transaction decorator for data consistency"
},
"entity": {
"decorators": ["@Entity", "@PrimaryGeneratedColumn", "@Column"],
"relationships": ["@ManyToOne", "@OneToMany", "@ManyToMany"],
"validation": "class-validator decorators on fields",
"timestamps": "Include createdAt, updatedAt with @CreateDateColumn"
},
"dto": {
"validation": "class-validator decorators (@IsString, @IsOptional)",
"transformation": "class-transformer decorators (@Transform, @Type)",
"swagger": "Swagger decorators (@ApiProperty, @ApiPropertyOptional)",
"inheritance": "Use PartialType, PickType for variations"
},
"testing": {
"unit": "Test services and controllers independently with mocks",
"integration": "Test complete request/response cycles",
"mocking": "Use jest.mock for dependencies",
"coverage": "Focus on business logic and edge cases"
}
},
"context7Libraries": [
"@nestjs/common",
"@nestjs/core",
"@nestjs/typeorm",
"@nestjs/swagger",
"@nestjs/jwt",
"@nestjs/passport",
"@nestjs/cache-manager",
"@nestjs/throttler",
"typeorm",
"class-validator",
"class-transformer",
"jest"
],
"commonImports": {
"controller": [
"import { Controller, Get, Post, Put, Delete, Patch, Body, Param, Query, UseGuards, HttpException, HttpStatus } from '@nestjs/common';",
"import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';"
],
"service": [
"import { Injectable } from '@nestjs/common';",
"import { InjectRepository } from '@nestjs/typeorm';",
"import { Repository } from 'typeorm';"
],
"entity": [
"import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';",
"import { IsString, IsOptional, IsNumber, IsBoolean, IsDate } from 'class-validator';"
],
"dto": [
"import { IsString, IsOptional, IsNumber, IsBoolean, IsEmail, IsArray } from 'class-validator';",
"import { Transform, Type } from 'class-transformer';",
"import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';"
]
},
"bestPractices": [
"Use dependency injection for all services and repositories",
"Validate all input data using DTOs with class-validator",
"Document all API endpoints with Swagger decorators",
"Implement proper error handling with custom exception filters",
"Use TypeORM repositories for database operations",
"Write unit tests for all services and integration tests for controllers",
"Use environment variables for configuration",
"Implement rate limiting and security guards",
"Use transactions for operations affecting multiple entities",
"Follow REST API conventions for endpoint naming"
],
"securityConsiderations": [
"Validate and sanitize all inputs",
"Use JWT authentication with proper token validation",
"Implement role-based access control (RBAC)",
"Use HTTPS in production environments",
"Implement rate limiting to prevent abuse",
"Hash passwords using bcrypt",
"Use parameterized queries to prevent SQL injection",
"Implement proper CORS configuration",
"Log security-relevant events for auditing",
"Use environment variables for sensitive configuration"
]
}

View File

@@ -0,0 +1,168 @@
{
"name": "Next.js Fullstack",
"description": "Next.js 14+ with App Router, TypeScript, Tailwind CSS, and modern fullstack development",
"filePatterns": ["*.tsx", "*.ts", "*.jsx", "*.js"],
"excludePatterns": ["*.test.tsx", "*.test.ts", "*.spec.tsx", "*.spec.ts", "*.d.ts"],
"techStack": {
"framework": "Next.js 14+ with App Router",
"language": "TypeScript",
"styling": "Tailwind CSS",
"database": "Prisma + PostgreSQL",
"authentication": "NextAuth.js",
"stateManagement": "Zustand + React Query",
"testing": "Jest + React Testing Library",
"deployment": "Vercel",
"api": "Next.js API Routes / Server Actions"
},
"conventions": {
"naming": {
"components": "PascalCase (UserProfile.tsx)",
"pages": "lowercase with hyphens (user-profile/page.tsx)",
"apiRoutes": "lowercase with hyphens (api/user-profile/route.ts)",
"hooks": "camelCase with use prefix (useAuth.ts)",
"utilities": "camelCase (formatDate.ts)",
"constants": "UPPER_SNAKE_CASE",
"types": "PascalCase with T prefix"
},
"fileStructure": {
"appRouter": "app/{route}/page.tsx, layout.tsx",
"apiRoutes": "app/api/{endpoint}/route.ts",
"components": "components/{feature}/{ComponentName}.tsx",
"hooks": "hooks/use{HookName}.ts",
"libs": "lib/{utility}.ts",
"types": "types/{feature}.types.ts",
"prisma": "prisma/schema.prisma, prisma/migrations/",
"tests": "__tests__/{ComponentName}.test.tsx"
},
"imports": {
"style": "Absolute imports with @ prefix",
"grouping": "React/Next, third-party, internal, relative",
"sorting": "Alphabetical within groups"
}
},
"qualityChecks": {
"lint": {
"command": "npx eslint --fix",
"config": "Next.js ESLint + TypeScript",
"autoFix": true
},
"format": {
"command": "npx prettier --write",
"config": "80 character line limit",
"autoFix": true
},
"build": {
"command": "npm run build",
"checkTypes": true,
"failOnError": true
},
"test": {
"unit": "npm test",
"coverage": "npm run test:coverage",
"minimumCoverage": 75
}
},
"codePatterns": {
"page": {
"structure": "Default export function with metadata",
"metadata": "Use generateMetadata for dynamic SEO",
"loading": "Create loading.tsx for loading states",
"error": "Create error.tsx for error boundaries",
"notFound": "Create not-found.tsx for 404 handling"
},
"layout": {
"structure": "Root layout with html and body tags",
"metadata": "Define default metadata and viewport",
"providers": "Wrap children with necessary providers",
"fonts": "Use next/font for font optimization"
},
"component": {
"client": "Use 'use client' directive for client components",
"server": "Default to server components when possible",
"props": "Define TypeScript interfaces for props",
"memo": "Use React.memo for performance when needed"
},
"apiRoute": {
"structure": "Export named functions (GET, POST, etc.)",
"params": "Use typed params and searchParams",
"responses": "Return NextResponse with proper status codes",
"middleware": "Use middleware for auth and validation"
},
"serverActions": {
"directive": "Use 'use server' directive",
"validation": "Validate input data with zod",
"revalidation": "Use revalidatePath/revalidateTag",
"errors": "Handle errors gracefully"
},
"database": {
"prisma": "Use Prisma Client for database operations",
"transactions": "Use Prisma transactions for complex operations",
"migrations": "Use Prisma migrate for schema changes",
"seeding": "Create seed scripts for development data"
}
},
"context7Libraries": [
"next",
"react",
"@next/font",
"next-auth",
"@prisma/client",
"prisma",
"tailwindcss",
"zustand",
"@tanstack/react-query",
"zod"
],
"commonImports": {
"page": ["import { Metadata } from 'next';", "import { notFound } from 'next/navigation';"],
"component": [
"import React from 'react';",
"import Link from 'next/link';",
"import Image from 'next/image';"
],
"apiRoute": [
"import { NextRequest, NextResponse } from 'next/server';",
"import { getServerSession } from 'next-auth';"
],
"serverAction": [
"import { revalidatePath } from 'next/cache';",
"import { redirect } from 'next/navigation';"
]
},
"bestPractices": [
"Use App Router instead of Pages Router for new projects",
"Default to Server Components, use Client Components only when needed",
"Use Next.js Image component for optimized images",
"Implement proper SEO with metadata API",
"Use Server Actions for form handling and mutations",
"Implement proper error handling with error boundaries",
"Use Prisma for type-safe database operations",
"Implement proper authentication with NextAuth.js",
"Use Tailwind CSS for styling with design system approach",
"Implement proper loading states and skeleton screens"
],
"seoOptimization": [
"Use generateMetadata for dynamic meta tags",
"Implement proper Open Graph and Twitter Card tags",
"Use structured data (JSON-LD) where appropriate",
"Implement proper canonical URLs",
"Use Next.js Image component with alt text",
"Implement proper heading hierarchy",
"Use semantic HTML elements",
"Generate sitemap.xml and robots.txt",
"Implement proper internal linking",
"Optimize Core Web Vitals"
],
"performanceOptimizations": [
"Use Next.js Image component with proper sizing",
"Implement code splitting with dynamic imports",
"Use React.lazy and Suspense for component lazy loading",
"Optimize fonts with next/font",
"Use streaming with loading.tsx files",
"Implement proper caching strategies",
"Use ISR (Incremental Static Regeneration) when appropriate",
"Optimize bundle size with proper imports",
"Use web workers for heavy computations",
"Implement proper database query optimization"
]
}

View File

@@ -0,0 +1,168 @@
{
"name": "Python FastAPI",
"description": "FastAPI with SQLAlchemy, Pydantic, and modern Python development practices",
"filePatterns": ["*.py"],
"excludePatterns": ["*_test.py", "*test*.py", "__pycache__/*"],
"techStack": {
"framework": "FastAPI",
"language": "Python 3.9+",
"database": "SQLAlchemy + PostgreSQL",
"validation": "Pydantic",
"testing": "Pytest + httpx",
"documentation": "OpenAPI/Swagger (auto-generated)",
"async": "asyncio + asyncpg",
"serialization": "Pydantic models"
},
"conventions": {
"naming": {
"variables": "snake_case",
"functions": "snake_case",
"classes": "PascalCase",
"constants": "UPPER_SNAKE_CASE",
"modules": "lowercase_with_underscores",
"packages": "lowercase"
},
"fileStructure": {
"routers": "app/routers/{feature}.py",
"models": "app/models/{feature}.py",
"schemas": "app/schemas/{feature}.py",
"services": "app/services/{feature}.py",
"database": "app/database.py",
"tests": "tests/test_{feature}.py"
},
"imports": {
"style": "Absolute imports from project root",
"grouping": "Standard library, third-party, local",
"sorting": "Alphabetical within groups"
}
},
"qualityChecks": {
"lint": {
"command": "flake8 .",
"config": "PEP 8 compliance",
"autoFix": false
},
"format": {
"command": "black .",
"config": "88 character line limit",
"autoFix": true
},
"typeCheck": {
"command": "mypy .",
"config": "Strict type checking",
"autoFix": false
},
"build": {
"command": "python -m compileall .",
"checkSyntax": true,
"failOnError": true
},
"test": {
"unit": "pytest tests/",
"coverage": "pytest --cov=app tests/",
"minimumCoverage": 80
}
},
"codePatterns": {
"router": {
"structure": "Use APIRouter with proper prefixes and tags",
"endpoints": "Async functions with proper HTTP methods",
"dependencies": "Use Depends() for dependency injection",
"responses": "Type-annotated response models",
"errors": "Use HTTPException for error handling"
},
"model": {
"sqlalchemy": "Use SQLAlchemy declarative base",
"relationships": "Properly define foreign keys and relationships",
"validation": "Include proper field constraints",
"timestamps": "Include created_at, updated_at fields"
},
"schema": {
"pydantic": "Use Pydantic BaseModel for request/response schemas",
"validation": "Include proper field validation",
"serialization": "Configure proper serialization options",
"inheritance": "Use inheritance for variations (Create, Update, Response)"
},
"service": {
"async": "Use async/await for database operations",
"transactions": "Implement proper transaction handling",
"error_handling": "Comprehensive error handling with custom exceptions",
"logging": "Structured logging for debugging and monitoring"
},
"testing": {
"fixtures": "Use pytest fixtures for test setup",
"client": "Use TestClient for endpoint testing",
"database": "Use separate test database",
"mocking": "Mock external dependencies and services"
}
},
"context7Libraries": [
"fastapi",
"sqlalchemy",
"pydantic",
"pytest",
"httpx",
"asyncpg",
"uvicorn",
"alembic"
],
"commonImports": {
"router": [
"from fastapi import APIRouter, Depends, HTTPException, status",
"from sqlalchemy.orm import Session",
"from app.database import get_db"
],
"model": [
"from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean",
"from sqlalchemy.ext.declarative import declarative_base",
"from sqlalchemy.orm import relationship",
"from datetime import datetime"
],
"schema": [
"from pydantic import BaseModel, EmailStr, validator",
"from typing import Optional, List",
"from datetime import datetime"
],
"service": [
"from sqlalchemy.orm import Session",
"from sqlalchemy.exc import IntegrityError",
"from fastapi import HTTPException, status"
]
},
"bestPractices": [
"Use async/await for I/O operations",
"Implement proper dependency injection with Depends()",
"Use Pydantic models for request/response validation",
"Follow PEP 8 style guidelines",
"Use type hints for all functions and variables",
"Implement proper error handling with HTTP status codes",
"Use SQLAlchemy for database operations with proper relationships",
"Write comprehensive tests with pytest",
"Use environment variables for configuration",
"Implement proper logging for debugging and monitoring"
],
"securityConsiderations": [
"Validate and sanitize all input data using Pydantic",
"Use proper authentication and authorization mechanisms",
"Hash passwords using secure algorithms (bcrypt)",
"Implement rate limiting to prevent abuse",
"Use HTTPS in production environments",
"Validate JWT tokens properly",
"Use parameterized queries to prevent SQL injection",
"Implement proper CORS configuration",
"Log security-relevant events for auditing",
"Use environment variables for sensitive configuration"
],
"asyncPatterns": [
"Use async def for route handlers that perform I/O",
"Use asyncio.gather() for concurrent operations",
"Implement proper connection pooling for database",
"Use async context managers for resource management",
"Handle exceptions properly in async functions",
"Use asyncio.create_task() for background tasks",
"Implement proper shutdown handling for async resources",
"Use async generators for streaming responses",
"Avoid blocking operations in async functions",
"Use proper async testing patterns with pytest-asyncio"
]
}

View File

@@ -0,0 +1,161 @@
{
"name": "React Frontend",
"description": "React 18+ with TypeScript, Tailwind CSS, and modern development practices",
"filePatterns": ["*.tsx", "*.ts", "*.jsx", "*.js"],
"excludePatterns": ["*.test.tsx", "*.test.ts", "*.spec.tsx", "*.spec.ts", "*.d.ts"],
"techStack": {
"framework": "React 18+",
"language": "TypeScript",
"styling": "Tailwind CSS",
"stateManagement": "React Query + Context API",
"routing": "React Router",
"testing": "React Testing Library + Jest",
"bundler": "Create React App / Vite",
"icons": "Heroicons + Lucide React",
"charts": "Chart.js + react-chartjs-2"
},
"conventions": {
"naming": {
"components": "PascalCase (UserProfile.tsx)",
"hooks": "camelCase with use prefix (useAuth.ts)",
"utilities": "camelCase (formatDate.ts)",
"constants": "UPPER_SNAKE_CASE",
"types": "PascalCase with T prefix",
"interfaces": "PascalCase with I prefix"
},
"fileStructure": {
"components": "src/components/{feature}/{ComponentName}.tsx",
"hooks": "src/hooks/use{HookName}.ts",
"services": "src/services/{feature}.service.ts",
"types": "src/types/{feature}.types.ts",
"contexts": "src/contexts/{Feature}Context.tsx",
"pages": "src/pages/{PageName}.tsx",
"tests": "src/components/{feature}/__tests__/{ComponentName}.test.tsx"
},
"imports": {
"style": "Absolute imports with @ prefix when available",
"grouping": "React, third-party, internal, relative",
"sorting": "Alphabetical within groups"
}
},
"qualityChecks": {
"lint": {
"command": "npx eslint --fix",
"config": "ESLint React + TypeScript + a11y",
"autoFix": true
},
"format": {
"command": "npx prettier --write",
"config": "80 character line limit, single quotes",
"autoFix": true
},
"build": {
"command": "npm run build",
"checkTypes": true,
"failOnError": true
},
"test": {
"unit": "npm test",
"coverage": "npm run test:coverage",
"minimumCoverage": 70
}
},
"codePatterns": {
"component": {
"structure": "Functional components with TypeScript interfaces",
"props": "Define interface for component props",
"state": "Use useState, useReducer for local state",
"effects": "Use useEffect with proper cleanup",
"memo": "Use React.memo for performance optimization when needed",
"forwardRef": "Use forwardRef for components that need ref access"
},
"hooks": {
"custom": "Extract reusable logic into custom hooks",
"naming": "Always start with 'use' prefix",
"dependencies": "Properly declare useEffect dependencies",
"cleanup": "Return cleanup functions from useEffect when needed"
},
"styling": {
"tailwind": "Use Tailwind utility classes",
"responsive": "Mobile-first responsive design",
"darkMode": "Support dark mode with Tailwind dark: prefix",
"accessibility": "Include proper ARIA labels and keyboard navigation"
},
"stateManagement": {
"local": "useState for component-local state",
"global": "Context API for app-wide state",
"server": "React Query for server state management",
"forms": "Controlled components with validation"
},
"testing": {
"render": "Use @testing-library/react render method",
"queries": "Use semantic queries (getByRole, getByLabelText)",
"userEvents": "Use @testing-library/user-event for interactions",
"mocking": "Mock external dependencies and API calls",
"accessibility": "Test with screen reader and keyboard navigation"
}
},
"context7Libraries": [
"react",
"react-dom",
"react-router-dom",
"@tanstack/react-query",
"tailwindcss",
"@testing-library/react",
"@testing-library/user-event",
"@heroicons/react",
"lucide-react",
"chart.js"
],
"commonImports": {
"component": [
"import React, { useState, useEffect, useCallback, useMemo } from 'react';",
"import { useNavigate, useParams } from 'react-router-dom';"
],
"hook": [
"import { useState, useEffect, useCallback, useContext } from 'react';",
"import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';"
],
"test": [
"import { render, screen, fireEvent, waitFor } from '@testing-library/react';",
"import userEvent from '@testing-library/user-event';",
"import { BrowserRouter } from 'react-router-dom';"
]
},
"bestPractices": [
"Use functional components with hooks instead of class components",
"Extract custom hooks for reusable stateful logic",
"Use React.memo for performance optimization when appropriate",
"Implement proper error boundaries for error handling",
"Use React Query for server state management",
"Follow accessibility guidelines (WCAG 2.1)",
"Implement responsive design with mobile-first approach",
"Use TypeScript for type safety",
"Write comprehensive tests for components and hooks",
"Optimize bundle size with code splitting and lazy loading"
],
"accessibilityRequirements": [
"Provide meaningful alt text for images",
"Use semantic HTML elements",
"Ensure proper heading hierarchy (h1, h2, h3)",
"Include ARIA labels for interactive elements",
"Support keyboard navigation for all interactive elements",
"Maintain sufficient color contrast ratios",
"Provide focus indicators for keyboard users",
"Use role attributes when semantic HTML is insufficient",
"Test with screen readers",
"Ensure form fields have associated labels"
],
"performanceOptimizations": [
"Use React.lazy for code splitting",
"Implement virtualization for long lists",
"Use useMemo and useCallback to prevent unnecessary re-renders",
"Optimize images with proper formats and sizes",
"Use React.memo for components that receive stable props",
"Implement proper error boundaries",
"Use React Query for efficient data fetching and caching",
"Minimize bundle size by importing only needed modules",
"Use web workers for heavy computations",
"Implement proper loading states and skeleton screens"
]
}

View File

@@ -0,0 +1,182 @@
{
"name": "API Development Workflow",
"description": "Standardized workflow for REST/GraphQL API endpoint development",
"workflowType": "api-development",
"applicablePatterns": ["REST", "GraphQL", "WebSocket"],
"phases": {
"planning": {
"description": "API design and specification phase",
"activities": [
"Define API contract and OpenAPI specification",
"Design request/response schemas",
"Plan error handling and status codes",
"Consider rate limiting and pagination",
"Document authentication and authorization requirements"
]
},
"implementation": {
"description": "Core API implementation phase",
"activities": [
"Create controller/resolver with proper routing",
"Implement service layer with business logic",
"Add input validation and sanitization",
"Implement proper error handling",
"Add authentication and authorization guards"
]
},
"testing": {
"description": "Comprehensive API testing phase",
"activities": [
"Write unit tests for service layer",
"Create integration tests for endpoints",
"Test error scenarios and edge cases",
"Validate API documentation accuracy",
"Perform security testing"
]
},
"documentation": {
"description": "API documentation and examples",
"activities": [
"Generate/update OpenAPI documentation",
"Create usage examples and tutorials",
"Document rate limits and quotas",
"Add error code documentation",
"Update API versioning information"
]
}
},
"implementationPatterns": {
"controller": {
"structure": "Thin controller with business logic in services",
"validation": "Use DTOs for input validation",
"responses": "Standardized response format",
"errors": "Consistent error handling middleware",
"documentation": "Comprehensive API documentation decorators"
},
"service": {
"business_logic": "Core business logic implementation",
"data_access": "Repository pattern for data operations",
"transactions": "Database transaction management",
"caching": "Implement caching where appropriate",
"external_apis": "Handle external API integrations"
},
"validation": {
"input": "Validate all input parameters and body data",
"sanitization": "Sanitize inputs to prevent injection attacks",
"authorization": "Verify user permissions for operations",
"rate_limiting": "Implement appropriate rate limiting",
"idempotency": "Support idempotent operations where needed"
},
"responses": {
"success": "Consistent success response format",
"errors": "Standardized error response structure",
"pagination": "Implement cursor or offset pagination",
"filtering": "Support query filtering and sorting",
"versioning": "Handle API versioning appropriately"
}
},
"qualityGates": {
"pre_implementation": [
"API specification reviewed and approved",
"Data models and schemas defined",
"Authentication requirements clarified",
"Rate limiting strategy determined",
"Error handling approach documented"
],
"implementation": [
"Code follows established patterns and conventions",
"Input validation implemented for all parameters",
"Proper error handling and logging added",
"Authentication and authorization enforced",
"Business logic separated from controller logic"
],
"testing": [
"Unit tests cover all service methods",
"Integration tests validate API contracts",
"Error scenarios properly tested",
"Performance tests pass acceptance criteria",
"Security tests identify no critical vulnerabilities"
],
"deployment": [
"API documentation is accurate and complete",
"Monitoring and alerting configured",
"Database migrations applied successfully",
"Configuration validated in target environment",
"Rollback procedures documented and tested"
]
},
"testingStrategy": {
"unit_tests": {
"scope": "Individual service methods and business logic",
"mocking": "Mock external dependencies and database",
"coverage": "Minimum 80% code coverage",
"focus": "Business logic and edge cases"
},
"integration_tests": {
"scope": "Full API endpoint testing with real database",
"scenarios": "Happy path and error scenarios",
"data": "Use test fixtures and factories",
"cleanup": "Clean up test data after each test"
},
"contract_tests": {
"scope": "API contract validation",
"tools": "OpenAPI validation and contract testing",
"versioning": "Backward compatibility testing",
"documentation": "Ensure examples work correctly"
},
"performance_tests": {
"scope": "Load and stress testing",
"metrics": "Response time, throughput, resource usage",
"scenarios": "Normal and peak load conditions",
"bottlenecks": "Identify and address performance issues"
},
"security_tests": {
"scope": "Authentication, authorization, and input validation",
"scenarios": "SQL injection, XSS, authentication bypass",
"tools": "Automated security scanning",
"compliance": "Ensure regulatory compliance requirements"
}
},
"codeTemplates": {
"restController": {
"framework": "universal",
"template": "// REST Controller Template\n@Controller('/api/v1/users')\n@ApiTags('users')\nexport class UsersController {\n constructor(private usersService: UsersService) {}\n\n @Get()\n @ApiOperation({ summary: 'Get all users' })\n @ApiResponse({ status: 200, description: 'Users retrieved successfully' })\n async getUsers(@Query() query: GetUsersDto): Promise<ApiResponse<User[]>> {\n const users = await this.usersService.getUsers(query);\n return { data: users, message: 'Users retrieved successfully' };\n }\n\n @Post()\n @ApiOperation({ summary: 'Create new user' })\n @ApiResponse({ status: 201, description: 'User created successfully' })\n async createUser(@Body() createUserDto: CreateUserDto): Promise<ApiResponse<User>> {\n const user = await this.usersService.createUser(createUserDto);\n return { data: user, message: 'User created successfully' };\n }\n}"
},
"serviceLayer": {
"framework": "universal",
"template": "// Service Layer Template\n@Injectable()\nexport class UsersService {\n constructor(private usersRepository: UsersRepository) {}\n\n async getUsers(query: GetUsersDto): Promise<User[]> {\n try {\n const users = await this.usersRepository.findWithFilters(query);\n return users;\n } catch (error) {\n throw new ServiceException('Failed to retrieve users', error);\n }\n }\n\n async createUser(createUserDto: CreateUserDto): Promise<User> {\n try {\n const existingUser = await this.usersRepository.findByEmail(createUserDto.email);\n if (existingUser) {\n throw new ConflictException('User with this email already exists');\n }\n \n const user = await this.usersRepository.create(createUserDto);\n return user;\n } catch (error) {\n throw new ServiceException('Failed to create user', error);\n }\n }\n}"
},
"integrationTest": {
"framework": "universal",
"template": "// Integration Test Template\ndescribe('Users API', () => {\n let app: TestingModule;\n let httpServer: any;\n\n beforeAll(async () => {\n app = await Test.createTestingModule({\n imports: [AppModule],\n }).compile();\n \n httpServer = app.createNestApplication();\n await httpServer.init();\n });\n\n describe('GET /api/v1/users', () => {\n it('should return users list', async () => {\n const response = await request(httpServer)\n .get('/api/v1/users')\n .expect(200);\n\n expect(response.body.data).toBeInstanceOf(Array);\n expect(response.body.message).toBe('Users retrieved successfully');\n });\n\n it('should handle pagination', async () => {\n const response = await request(httpServer)\n .get('/api/v1/users?page=1&limit=10')\n .expect(200);\n\n expect(response.body.data.length).toBeLessThanOrEqual(10);\n });\n });\n\n describe('POST /api/v1/users', () => {\n it('should create new user', async () => {\n const newUser = {\n name: 'John Doe',\n email: 'john@example.com'\n };\n\n const response = await request(httpServer)\n .post('/api/v1/users')\n .send(newUser)\n .expect(201);\n\n expect(response.body.data.name).toBe(newUser.name);\n expect(response.body.data.email).toBe(newUser.email);\n });\n\n it('should validate required fields', async () => {\n const response = await request(httpServer)\n .post('/api/v1/users')\n .send({})\n .expect(400);\n\n expect(response.body.errors).toBeDefined();\n });\n });\n});"
}
},
"bestPractices": [
"Use consistent REST conventions for endpoint naming",
"Implement proper HTTP status codes for different scenarios",
"Add comprehensive input validation and sanitization",
"Use DTOs for request/response data structures",
"Implement proper error handling with meaningful messages",
"Add rate limiting to prevent API abuse",
"Use pagination for endpoints returning large datasets",
"Implement API versioning strategy from the start",
"Add comprehensive logging for debugging and monitoring",
"Use dependency injection for better testability",
"Implement proper authentication and authorization",
"Add API documentation with examples and use cases"
],
"commonPitfalls": [
"Putting business logic directly in controllers",
"Not validating input parameters properly",
"Inconsistent error handling and response formats",
"Missing or outdated API documentation",
"Not implementing proper pagination",
"Ignoring rate limiting and abuse prevention",
"Poor error messages that don't help clients",
"Not versioning APIs properly",
"Missing or inadequate logging",
"Not testing error scenarios thoroughly",
"Exposing sensitive information in error responses",
"Not handling database connection failures gracefully"
]
}

View File

@@ -0,0 +1,201 @@
{
"name": "Frontend Component Development",
"description": "Standardized workflow for React/Vue component development with accessibility and testing",
"workflowType": "frontend-component",
"applicablePatterns": ["React", "Vue", "Angular", "Web Components"],
"phases": {
"design": {
"description": "Component design and specification phase",
"activities": [
"Define component API and props interface",
"Create component design system documentation",
"Plan responsive behavior and breakpoints",
"Design accessibility features and ARIA labels",
"Consider component composition and reusability"
]
},
"implementation": {
"description": "Core component implementation phase",
"activities": [
"Create component with TypeScript interfaces",
"Implement responsive styling with CSS/Tailwind",
"Add accessibility features (ARIA, keyboard navigation)",
"Implement component state management",
"Add proper error boundaries and loading states"
]
},
"testing": {
"description": "Comprehensive component testing phase",
"activities": [
"Write unit tests for component logic",
"Create integration tests with user interactions",
"Test accessibility with screen readers",
"Validate responsive behavior across devices",
"Test component with different prop combinations"
]
},
"documentation": {
"description": "Component documentation and examples",
"activities": [
"Create Storybook stories for all variants",
"Document component API and usage examples",
"Add accessibility guidelines and best practices",
"Create interactive documentation",
"Document component performance characteristics"
]
}
},
"implementationPatterns": {
"structure": {
"functional": "Use functional components with hooks",
"typescript": "Define proper TypeScript interfaces for props",
"composition": "Design for component composition and reusability",
"separation": "Separate logic, presentation, and styling concerns",
"naming": "Use descriptive and consistent naming conventions"
},
"styling": {
"responsive": "Mobile-first responsive design approach",
"design_tokens": "Use design tokens for consistency",
"css_modules": "Scoped styling to prevent conflicts",
"accessibility": "Ensure sufficient color contrast and focus indicators",
"dark_mode": "Support light and dark theme variations"
},
"accessibility": {
"semantic_html": "Use semantic HTML elements when possible",
"aria_labels": "Add appropriate ARIA labels and descriptions",
"keyboard_nav": "Implement full keyboard navigation support",
"screen_readers": "Ensure screen reader compatibility",
"focus_management": "Proper focus management and indicators"
},
"state_management": {
"local_state": "Use useState for component-local state",
"side_effects": "Use useEffect with proper cleanup",
"performance": "Use useMemo and useCallback for optimization",
"context": "Use React Context for component tree state",
"forms": "Controlled components with proper validation"
},
"error_handling": {
"boundaries": "Implement error boundaries for error containment",
"validation": "Input validation with user-friendly messages",
"loading_states": "Proper loading and skeleton states",
"fallbacks": "Graceful degradation for component failures",
"user_feedback": "Clear feedback for user actions"
}
},
"qualityGates": {
"design": [
"Component API designed with reusability in mind",
"Accessibility requirements identified and documented",
"Responsive behavior planned for all breakpoints",
"Design tokens and styling approach determined",
"Component composition strategy defined"
],
"implementation": [
"TypeScript interfaces defined for all props",
"Component implements planned accessibility features",
"Responsive behavior works across all target devices",
"Component follows established coding patterns",
"Error handling and edge cases addressed"
],
"testing": [
"Unit tests cover all component logic and edge cases",
"Accessibility tests pass with screen reader testing",
"Integration tests validate user interaction flows",
"Visual regression tests prevent styling issues",
"Performance tests meet established benchmarks"
],
"documentation": [
"Storybook stories demonstrate all component variants",
"API documentation is complete and accurate",
"Usage examples and best practices documented",
"Accessibility guidelines provided",
"Performance characteristics documented"
]
},
"testingStrategy": {
"unit_tests": {
"scope": "Component logic, prop handling, and state changes",
"tools": "React Testing Library, Jest",
"coverage": "Minimum 85% code coverage",
"focus": "User interactions and business logic"
},
"accessibility_tests": {
"scope": "ARIA labels, keyboard navigation, screen reader compatibility",
"tools": "axe-core, @testing-library/jest-dom",
"manual": "Manual testing with actual screen readers",
"standards": "WCAG 2.1 AA compliance"
},
"visual_tests": {
"scope": "Component appearance across different states",
"tools": "Chromatic, Percy, or similar visual testing",
"devices": "Test across multiple device sizes",
"themes": "Test light/dark theme variations"
},
"integration_tests": {
"scope": "Component behavior within larger application context",
"user_flows": "End-to-end user interaction scenarios",
"data_flow": "Test with real or realistic data",
"performance": "Component performance under load"
},
"responsive_tests": {
"scope": "Component behavior across different screen sizes",
"breakpoints": "Test all defined responsive breakpoints",
"orientation": "Portrait and landscape orientations",
"devices": "Physical device testing when possible"
}
},
"codeTemplates": {
"reactComponent": {
"framework": "React",
"template": "import React, { useState, useEffect, useCallback } from 'react';\nimport { cn } from '@/lib/utils';\n\ninterface ComponentNameProps {\n /** Primary content for the component */\n children?: React.ReactNode;\n /** Additional CSS class names */\n className?: string;\n /** Component variant */\n variant?: 'primary' | 'secondary' | 'outline';\n /** Component size */\n size?: 'sm' | 'md' | 'lg';\n /** Disabled state */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\n/**\n * ComponentName - Brief description of what this component does\n * \n * @example\n * <ComponentName variant=\"primary\" size=\"md\">\n * Content goes here\n * </ComponentName>\n */\nexport const ComponentName: React.FC<ComponentNameProps> = ({\n children,\n className,\n variant = 'primary',\n size = 'md',\n disabled = false,\n onClick,\n ...props\n}) => {\n const [isActive, setIsActive] = useState(false);\n\n const handleClick = useCallback(() => {\n if (!disabled && onClick) {\n onClick();\n }\n }, [disabled, onClick]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleClick();\n }\n }, [handleClick]);\n\n return (\n <button\n className={cn(\n // Base styles\n 'inline-flex items-center justify-center rounded-md font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n \n // Variant styles\n {\n 'bg-primary text-primary-foreground hover:bg-primary/90': variant === 'primary',\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80': variant === 'secondary',\n 'border border-input hover:bg-accent hover:text-accent-foreground': variant === 'outline',\n },\n \n // Size styles\n {\n 'h-8 px-3 text-sm': size === 'sm',\n 'h-10 px-4 py-2': size === 'md',\n 'h-12 px-6 text-lg': size === 'lg',\n },\n \n // State styles\n {\n 'opacity-50 cursor-not-allowed': disabled,\n },\n \n className\n )}\n disabled={disabled}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n {...props}\n >\n {children}\n </button>\n );\n};\n\nComponentName.displayName = 'ComponentName';"
},
"componentTest": {
"framework": "React Testing Library",
"template": "import { render, screen, fireEvent, waitFor } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\nimport { axe, toHaveNoViolations } from 'jest-axe';\nimport { ComponentName } from './ComponentName';\n\n// Extend Jest matchers\nexpect.extend(toHaveNoViolations);\n\ndescribe('ComponentName', () => {\n const user = userEvent.setup();\n\n it('renders with default props', () => {\n render(<ComponentName>Test Content</ComponentName>);\n \n const button = screen.getByRole('button', { name: 'Test Content' });\n expect(button).toBeInTheDocument();\n expect(button).toHaveClass('bg-primary'); // default variant\n });\n\n it('handles click events', async () => {\n const handleClick = jest.fn();\n render(\n <ComponentName onClick={handleClick}>\n Click me\n </ComponentName>\n );\n\n const button = screen.getByRole('button', { name: 'Click me' });\n await user.click(button);\n \n expect(handleClick).toHaveBeenCalledTimes(1);\n });\n\n it('supports keyboard navigation', async () => {\n const handleClick = jest.fn();\n render(\n <ComponentName onClick={handleClick}>\n Press Enter\n </ComponentName>\n );\n\n const button = screen.getByRole('button', { name: 'Press Enter' });\n button.focus();\n \n await user.keyboard('{Enter}');\n expect(handleClick).toHaveBeenCalledTimes(1);\n \n await user.keyboard(' ');\n expect(handleClick).toHaveBeenCalledTimes(2);\n });\n\n it('handles disabled state correctly', async () => {\n const handleClick = jest.fn();\n render(\n <ComponentName disabled onClick={handleClick}>\n Disabled\n </ComponentName>\n );\n\n const button = screen.getByRole('button', { name: 'Disabled' });\n expect(button).toBeDisabled();\n expect(button).toHaveAttribute('aria-disabled', 'true');\n \n await user.click(button);\n expect(handleClick).not.toHaveBeenCalled();\n });\n\n it('applies correct variant styles', () => {\n const { rerender } = render(\n <ComponentName variant=\"secondary\">\n Secondary\n </ComponentName>\n );\n \n let button = screen.getByRole('button');\n expect(button).toHaveClass('bg-secondary');\n \n rerender(\n <ComponentName variant=\"outline\">\n Outline\n </ComponentName>\n );\n \n button = screen.getByRole('button');\n expect(button).toHaveClass('border');\n });\n\n it('has no accessibility violations', async () => {\n const { container } = render(\n <ComponentName>\n Accessible Button\n </ComponentName>\n );\n \n const results = await axe(container);\n expect(results).toHaveNoViolations();\n });\n\n it('supports custom className', () => {\n render(\n <ComponentName className=\"custom-class\">\n Custom\n </ComponentName>\n );\n \n const button = screen.getByRole('button');\n expect(button).toHaveClass('custom-class');\n });\n});"
},
"storybookStory": {
"framework": "Storybook",
"template": "import type { Meta, StoryObj } from '@storybook/react';\nimport { ComponentName } from './ComponentName';\n\nconst meta: Meta<typeof ComponentName> = {\n title: 'Components/ComponentName',\n component: ComponentName,\n parameters: {\n layout: 'centered',\n docs: {\n description: {\n component: 'A versatile button component with multiple variants and sizes.',\n },\n },\n },\n argTypes: {\n variant: {\n control: 'select',\n options: ['primary', 'secondary', 'outline'],\n description: 'The visual variant of the button',\n },\n size: {\n control: 'select', \n options: ['sm', 'md', 'lg'],\n description: 'The size of the button',\n },\n disabled: {\n control: 'boolean',\n description: 'Whether the button is disabled',\n },\n onClick: {\n action: 'clicked',\n description: 'Function called when button is clicked',\n },\n },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\n// Default story\nexport const Default: Story = {\n args: {\n children: 'Button',\n variant: 'primary',\n size: 'md',\n disabled: false,\n },\n};\n\n// Variants showcase\nexport const Variants: Story = {\n render: () => (\n <div className=\"flex gap-4\">\n <ComponentName variant=\"primary\">Primary</ComponentName>\n <ComponentName variant=\"secondary\">Secondary</ComponentName>\n <ComponentName variant=\"outline\">Outline</ComponentName>\n </div>\n ),\n};\n\n// Sizes showcase\nexport const Sizes: Story = {\n render: () => (\n <div className=\"flex items-center gap-4\">\n <ComponentName size=\"sm\">Small</ComponentName>\n <ComponentName size=\"md\">Medium</ComponentName>\n <ComponentName size=\"lg\">Large</ComponentName>\n </div>\n ),\n};\n\n// Disabled state\nexport const Disabled: Story = {\n args: {\n children: 'Disabled Button',\n disabled: true,\n },\n};\n\n// Interactive example\nexport const Interactive: Story = {\n render: () => {\n const [count, setCount] = React.useState(0);\n return (\n <div className=\"text-center\">\n <p className=\"mb-4\">Count: {count}</p>\n <ComponentName onClick={() => setCount(count + 1)}>\n Increment\n </ComponentName>\n </div>\n );\n },\n};"
}
},
"accessibilityRequirements": [
"Use semantic HTML elements when possible (button, input, etc.)",
"Provide meaningful alt text for images",
"Ensure sufficient color contrast (4.5:1 for normal text)",
"Support keyboard navigation for all interactive elements",
"Use ARIA labels and descriptions where needed",
"Implement proper focus management and indicators",
"Support screen readers with appropriate ARIA attributes",
"Test with actual assistive technologies",
"Provide skip links for navigation",
"Use proper heading hierarchy",
"Ensure form labels are properly associated",
"Implement error states with clear messaging"
],
"performanceOptimizations": [
"Use React.memo for components that receive stable props",
"Implement useMemo for expensive calculations",
"Use useCallback for event handlers passed to child components",
"Optimize images with proper formats and lazy loading",
"Implement virtualization for large lists",
"Use code splitting for large components",
"Minimize bundle size by importing only needed modules",
"Use CSS-in-JS efficiently to avoid style recalculations",
"Implement proper error boundaries to prevent crashes",
"Monitor component re-render frequency and optimize"
],
"bestPractices": [
"Design components for reusability and composition",
"Use TypeScript for better development experience and catch errors",
"Follow accessibility guidelines from the start",
"Write comprehensive tests including accessibility tests",
"Document components with clear examples and usage",
"Use consistent naming conventions across components",
"Implement proper error handling and loading states",
"Consider mobile-first responsive design",
"Use design tokens for consistent styling",
"Optimize for performance without premature optimization",
"Follow the principle of least privilege for component APIs",
"Use proper semantic HTML for better accessibility"
]
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,38 @@
# Mosaic Bootstrap — Remote Installer (Windows PowerShell)
#
# One-liner:
# irm https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.ps1 | iex
#
# Or explicit:
# powershell -ExecutionPolicy Bypass -File remote-install.ps1
#
$ErrorActionPreference = "Stop"
$BootstrapRef = if ($env:MOSAIC_BOOTSTRAP_REF) { $env:MOSAIC_BOOTSTRAP_REF } else { "main" }
$ArchiveUrl = "https://git.mosaicstack.dev/mosaic/bootstrap/archive/$BootstrapRef.zip"
$WorkDir = Join-Path $env:TEMP "mosaic-bootstrap-$PID"
$ZipPath = "$WorkDir.zip"
try {
Write-Host "[mosaic] Downloading bootstrap archive (ref: $BootstrapRef)..."
New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null
Invoke-WebRequest -Uri $ArchiveUrl -OutFile $ZipPath -UseBasicParsing
Write-Host "[mosaic] Extracting..."
Expand-Archive -Path $ZipPath -DestinationPath $WorkDir -Force
$InstallScript = Join-Path $WorkDir "bootstrap\install.ps1"
if (-not (Test-Path $InstallScript)) {
throw "install.ps1 not found in archive"
}
Write-Host "[mosaic] Running install..."
& $InstallScript
Write-Host "[mosaic] Done."
}
finally {
Write-Host "[mosaic] Cleaning up temporary files..."
Remove-Item -Path $ZipPath -Force -ErrorAction SilentlyContinue
Remove-Item -Path $WorkDir -Recurse -Force -ErrorAction SilentlyContinue
}