Compare commits
2 Commits
feat/frame
...
fix/instal
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a58c51872 | |||
| 026382325c |
16
AGENTS.md
16
AGENTS.md
@@ -58,14 +58,14 @@ pnpm typecheck && pnpm lint && pnpm format:check # Quality gates
|
||||
|
||||
The `agent` column specifies the required model for each task. **This is set at task creation by the orchestrator and must not be changed by workers.**
|
||||
|
||||
| Value | When to use | Budget |
|
||||
| -------- | ----------------------------------------------------------- | -------------------------- |
|
||||
| `codex` | All coding tasks (default for implementation) | OpenAI credits — preferred |
|
||||
| `glm-5` | Cost-sensitive coding where Codex is unavailable | Z.ai credits |
|
||||
| `haiku` | Review gates, verify tasks, status checks, docs-only | Cheapest Claude tier |
|
||||
| `sonnet` | Complex planning, multi-file reasoning, architecture review | Claude quota |
|
||||
| `opus` | Major cross-cutting architecture decisions ONLY | Most expensive — minimize |
|
||||
| `—` | No preference / auto-select cheapest capable | Pipeline decides |
|
||||
| Value | When to use | Budget |
|
||||
| --------- | ----------------------------------------------------------- | -------------------------- |
|
||||
| `codex` | All coding tasks (default for implementation) | OpenAI credits — preferred |
|
||||
| `glm-5.1` | Cost-sensitive coding where Codex is unavailable | Z.ai credits |
|
||||
| `haiku` | Review gates, verify tasks, status checks, docs-only | Cheapest Claude tier |
|
||||
| `sonnet` | Complex planning, multi-file reasoning, architecture review | Claude quota |
|
||||
| `opus` | Major cross-cutting architecture decisions ONLY | Most expensive — minimize |
|
||||
| `—` | No preference / auto-select cheapest capable | Pipeline decides |
|
||||
|
||||
Pipeline crons read this column and spawn accordingly. Workers never modify `docs/TASKS.md` — only the orchestrator writes it.
|
||||
|
||||
|
||||
@@ -73,6 +73,27 @@ Spawn a worker instead. No exceptions. No "quick fixes."
|
||||
- Wait for at least one worker to complete before spawning more
|
||||
- This optimizes token usage and reduces context pressure
|
||||
|
||||
## File Ownership & Partitioning (Hard Rule for Parallel Workers)
|
||||
|
||||
When dispatching parallel workers, the orchestrator MUST assign **non-overlapping file scopes** to each worker. File collisions between parallel workers cause merge conflicts, lost edits, and wasted tokens.
|
||||
|
||||
**Rules:**
|
||||
|
||||
1. **Exclusive file ownership.** Each file may be assigned to at most one active worker. The orchestrator records ownership in the worker dispatch (prompt or task definition).
|
||||
2. **Partition by directory or module.** Prefer assigning entire directories/modules to one worker rather than splitting files within a directory across workers.
|
||||
3. **Shared files are serialized.** If two tasks must modify the same file (e.g., a shared types file, a barrel export), they MUST run sequentially — never in parallel. Mark the second task with `depends_on` pointing to the first.
|
||||
4. **Test files follow source ownership.** If Worker A owns `src/auth/login.ts`, Worker A also owns `src/auth/__tests__/login.test.ts`. Do not split source and test across workers.
|
||||
5. **Config files are orchestrator-reserved.** Files like `package.json`, `tsconfig.json`, and CI config are owned by the orchestrator and modified only between worker cycles, never during parallel execution.
|
||||
6. **Document ownership in dispatch.** When spawning a worker, include an explicit `Files:` section listing owned paths/globs. Example:
|
||||
|
||||
```
|
||||
Files (exclusive — do not touch files outside this scope):
|
||||
- apps/web/src/components/auth/**
|
||||
- apps/web/src/lib/auth.ts
|
||||
```
|
||||
|
||||
7. **Conflict recovery.** If a worker edits a file outside its scope, the orchestrator MUST flag the violation, assess the diff, and either revert the out-of-scope change or re-run the affected worker with the corrected file.
|
||||
|
||||
## Delegation Mode Selection
|
||||
|
||||
Choose one delegation mode at session start:
|
||||
|
||||
@@ -151,11 +151,68 @@ When delegating work to subagents, you MUST select the cheapest model capable of
|
||||
|
||||
**Runtime-specific syntax**: See the runtime reference for how to specify model tier when spawning subagents (e.g., Claude Code Task tool `model` parameter).
|
||||
|
||||
## Superpowers Enforcement (Hard Rule)
|
||||
|
||||
Mosaic provides capabilities beyond basic code editing: **skills**, **hooks**, **MCP tools**, and **plugins**. These are not optional extras — they are force multipliers that agents MUST actively use when applicable. Under-utilization of superpowers is a framework violation.
|
||||
|
||||
### Skills
|
||||
|
||||
Skills are domain-specific instruction sets in `~/.config/mosaic/skills/` that encode best practices, patterns, and guardrails. They are loaded into agents via the runtime's skill mechanism (e.g., Claude Code slash commands, Pi `--skill` flag).
|
||||
|
||||
**Rules:**
|
||||
|
||||
1. Before starting implementation, scan available skills (`ls ~/.config/mosaic/skills/`) and load any that match the task domain.
|
||||
2. When a skill exists for the technology being used (e.g., `nestjs-best-practices` for NestJS work), you MUST load it.
|
||||
3. When spawning workers, include skill loading in the kickstart prompt.
|
||||
4. If you complete a task without loading a relevant available skill, that is a quality gap.
|
||||
|
||||
### Hooks
|
||||
|
||||
Hooks provide automated quality gates (lint, format, typecheck) that fire on file edits. They are configured in the runtime settings and run automatically.
|
||||
|
||||
**Rules:**
|
||||
|
||||
1. Do NOT bypass or suppress hook output. If a hook reports errors, fix them before proceeding.
|
||||
2. Hook failures are immediate feedback — treat them like failing tests.
|
||||
3. If a hook is consistently failing on valid code, report it as a framework issue rather than working around it.
|
||||
|
||||
### MCP Tools
|
||||
|
||||
MCP servers extend agent capabilities with external integrations (sequential-thinking, web search, memory, browser automation, etc.). Available MCP tools are listed at session start.
|
||||
|
||||
**Rules:**
|
||||
|
||||
1. **sequential-thinking** is REQUIRED for planning, architecture, and multi-step reasoning. Use it — do not skip structured thinking for complex decisions.
|
||||
2. **OpenBrain** (`capture`, `search`, `recent`) is the cross-agent memory layer. Capture discoveries and search for prior context at session start.
|
||||
3. When a task involves web research, browser testing, or external data, use the available MCP tools (web-search, chrome-devtools, web-reader) rather than asking the user to look things up.
|
||||
4. Check available MCP tools at session start and use them proactively throughout the session.
|
||||
|
||||
### Plugins (Runtime-Specific)
|
||||
|
||||
Runtime plugins (e.g., Claude Code's `feature-dev`, `pr-review-toolkit`, `code-review`) provide specialized agent capabilities like code review, architecture analysis, and test coverage analysis.
|
||||
|
||||
**Rules:**
|
||||
|
||||
1. After completing a significant code change, use code review plugins proactively — do not wait for the user to ask.
|
||||
2. Before creating a PR, use PR review plugins to catch issues early.
|
||||
3. When designing architecture, use planning/architecture plugins for structured analysis.
|
||||
|
||||
### Self-Evolution
|
||||
|
||||
The Mosaic framework should improve over time based on usage patterns:
|
||||
|
||||
1. When you discover a recurring pattern that should be codified, capture it to OpenBrain with `type: "framework-improvement"`.
|
||||
2. When a hook, skill, or tool is missing for a common task, capture the gap to OpenBrain with `type: "tooling-gap"`.
|
||||
3. When a framework rule causes friction without adding value, capture the observation to OpenBrain with `type: "framework-friction"`.
|
||||
|
||||
These captures feed the framework's continuous improvement cycle.
|
||||
|
||||
## Skills Policy
|
||||
|
||||
- Use only the minimum required skills for the active task.
|
||||
- Load skills that match the active task domain before starting implementation.
|
||||
- Do not load unrelated skills.
|
||||
- Follow skill trigger rules from the active runtime instruction layer.
|
||||
- Actively check `~/.config/mosaic/skills/` for applicable skills rather than passively waiting for them to be mentioned.
|
||||
|
||||
## Session Closure Requirement
|
||||
|
||||
|
||||
@@ -19,8 +19,9 @@ SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TARGET_DIR="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
||||
INSTALL_MODE="${MOSAIC_INSTALL_MODE:-prompt}"
|
||||
|
||||
# Files preserved across upgrades (never overwritten)
|
||||
PRESERVE_PATHS=("SOUL.md" "USER.md" "TOOLS.md" "memory" "sources")
|
||||
# Files/dirs preserved across upgrades (never overwritten).
|
||||
# User-created content in these paths survives rsync --delete.
|
||||
PRESERVE_PATHS=("AGENTS.md" "SOUL.md" "USER.md" "TOOLS.md" "STANDARDS.md" "memory" "sources" "credentials")
|
||||
|
||||
# Current framework schema version — bump this when the layout changes.
|
||||
# The migration system uses this to run upgrade steps.
|
||||
@@ -217,8 +218,22 @@ fi
|
||||
|
||||
sync_framework
|
||||
|
||||
# Ensure memory directory exists
|
||||
# Ensure persistent directories exist
|
||||
mkdir -p "$TARGET_DIR/memory"
|
||||
mkdir -p "$TARGET_DIR/credentials"
|
||||
|
||||
# Seed defaults — copy from defaults/ to framework root if not already present.
|
||||
# These are user-editable files that ship with sensible defaults but should
|
||||
# never be overwritten once the user has customized them.
|
||||
DEFAULTS_DIR="$TARGET_DIR/defaults"
|
||||
if [[ -d "$DEFAULTS_DIR" ]]; then
|
||||
for default_file in AGENTS.md STANDARDS.md; do
|
||||
if [[ -f "$DEFAULTS_DIR/$default_file" ]] && [[ ! -f "$TARGET_DIR/$default_file" ]]; then
|
||||
cp "$DEFAULTS_DIR/$default_file" "$TARGET_DIR/$default_file"
|
||||
ok "Seeded $default_file from defaults"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Ensure tool scripts are executable
|
||||
find "$TARGET_DIR/tools" -name "*.sh" -exec chmod +x {} + 2>/dev/null || true
|
||||
|
||||
@@ -102,3 +102,30 @@ claude mcp add --scope user <name> -- npx -y <package>
|
||||
`--scope local` = default, local-only (not committed).
|
||||
|
||||
Do NOT add `mcpServers` to `~/.claude/settings.json` — that key is ignored for MCP loading.
|
||||
|
||||
## Required Claude Code Settings (Enforced by Launcher)
|
||||
|
||||
The `mosaic claude` launcher validates that `~/.claude/settings.json` contains the required Mosaic configuration. Missing or outdated settings trigger a warning at launch.
|
||||
|
||||
**Required hooks:**
|
||||
|
||||
| Event | Matcher | Script | Purpose |
|
||||
| ----------- | ------------------------ | ------------------------- | ---------------------------------------------- |
|
||||
| PreToolUse | `Write\|Edit\|MultiEdit` | `prevent-memory-write.sh` | Block writes to `~/.claude/projects/*/memory/` |
|
||||
| PostToolUse | `Edit\|MultiEdit\|Write` | `qa-hook-stdin.sh` | QA report generation after code edits |
|
||||
| PostToolUse | `Edit\|MultiEdit\|Write` | `typecheck-hook.sh` | Inline TypeScript type checking |
|
||||
|
||||
**Required plugins:**
|
||||
|
||||
| Plugin | Purpose |
|
||||
| ------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `feature-dev` | Subagent architecture: code-reviewer, code-architect, code-explorer |
|
||||
| `pr-review-toolkit` | PR review: code-simplifier, comment-analyzer, test-analyzer, silent-failure-hunter, type-design-analyzer |
|
||||
| `code-review` | Standalone code review capabilities |
|
||||
|
||||
**Required settings:**
|
||||
|
||||
- `enableAllMcpTools: true` — Allow all configured MCP tools without per-tool approval
|
||||
- `model: "opus"` — Default to opus for orchestrator-level sessions (workers use tiered models via Task tool)
|
||||
|
||||
If `mosaic claude` detects missing hooks or plugins, it will print a warning with the exact settings to add. The session will still launch — enforcement is advisory, not blocking — but agents operating without these settings are running degraded.
|
||||
|
||||
@@ -23,6 +23,16 @@
|
||||
"timeout": 60
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "Edit|MultiEdit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "~/.config/mosaic/tools/qa/typecheck-hook.sh",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
63
packages/mosaic/framework/tools/qa/typecheck-hook.sh
Executable file
63
packages/mosaic/framework/tools/qa/typecheck-hook.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# Lightweight PostToolUse typecheck hook for TypeScript files.
|
||||
# Runs tsc --noEmit on the nearest tsconfig after TS/TSX edits.
|
||||
# Returns non-zero with diagnostic output so the agent sees type errors immediately.
|
||||
# Location: ~/.config/mosaic/tools/qa/typecheck-hook.sh
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
# Read JSON from stdin (Claude Code PostToolUse payload)
|
||||
JSON_INPUT=$(cat)
|
||||
|
||||
# Extract file path
|
||||
if command -v jq &>/dev/null; then
|
||||
FILE_PATH=$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // .tool_response.filePath // .file_path // empty' 2>/dev/null || echo "")
|
||||
else
|
||||
FILE_PATH=$(echo "$JSON_INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/' | head -1)
|
||||
fi
|
||||
|
||||
# Only check TypeScript files
|
||||
if ! [[ "$FILE_PATH" =~ \.(ts|tsx)$ ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Must be a real file
|
||||
if [ ! -f "$FILE_PATH" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Find nearest tsconfig.json by walking up from the file
|
||||
DIR=$(dirname "$FILE_PATH")
|
||||
TSCONFIG=""
|
||||
while [ "$DIR" != "/" ] && [ "$DIR" != "." ]; do
|
||||
if [ -f "$DIR/tsconfig.json" ]; then
|
||||
TSCONFIG="$DIR/tsconfig.json"
|
||||
break
|
||||
fi
|
||||
DIR=$(dirname "$DIR")
|
||||
done
|
||||
|
||||
if [ -z "$TSCONFIG" ]; then
|
||||
# No tsconfig found — skip silently
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run tsc --noEmit from the tsconfig directory
|
||||
# Use --pretty for readable output, limit to 10 errors to keep output short
|
||||
TSCONFIG_DIR=$(dirname "$TSCONFIG")
|
||||
cd "$TSCONFIG_DIR"
|
||||
|
||||
# Run typecheck — capture output and exit code
|
||||
OUTPUT=$(npx tsc --noEmit --pretty --maxNodeModuleJsDepth 0 2>&1) || STATUS=$?
|
||||
|
||||
if [ "${STATUS:-0}" -ne 0 ]; then
|
||||
# Filter output to only show errors related to the edited file (if possible)
|
||||
BASENAME=$(basename "$FILE_PATH")
|
||||
RELEVANT=$(echo "$OUTPUT" | grep -A2 "$BASENAME" 2>/dev/null || echo "$OUTPUT" | head -20)
|
||||
|
||||
echo "TypeScript type errors detected after editing $FILE_PATH:"
|
||||
echo "$RELEVANT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -78,6 +78,82 @@ function checkSoul(): void {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Claude settings validation ─────────────────────────────────────────────
|
||||
|
||||
interface SettingsAudit {
|
||||
warnings: string[];
|
||||
}
|
||||
|
||||
function auditClaudeSettings(): SettingsAudit {
|
||||
const warnings: string[] = [];
|
||||
const settingsPath = join(homedir(), '.claude', 'settings.json');
|
||||
const settings = readJson(settingsPath);
|
||||
|
||||
if (!settings) {
|
||||
warnings.push('~/.claude/settings.json not found — hooks and plugins will be missing');
|
||||
return { warnings };
|
||||
}
|
||||
|
||||
// Check required hooks
|
||||
const hooks = settings['hooks'] as Record<string, unknown[]> | undefined;
|
||||
|
||||
const requiredPreToolUse = ['prevent-memory-write.sh'];
|
||||
const requiredPostToolUse = ['qa-hook-stdin.sh', 'typecheck-hook.sh'];
|
||||
|
||||
const preHooks = (hooks?.['PreToolUse'] ?? []) as Array<Record<string, unknown>>;
|
||||
const postHooks = (hooks?.['PostToolUse'] ?? []) as Array<Record<string, unknown>>;
|
||||
|
||||
const preCommands = preHooks.flatMap((h) => {
|
||||
const inner = (h['hooks'] ?? []) as Array<Record<string, unknown>>;
|
||||
return inner.map((ih) => String(ih['command'] ?? ''));
|
||||
});
|
||||
const postCommands = postHooks.flatMap((h) => {
|
||||
const inner = (h['hooks'] ?? []) as Array<Record<string, unknown>>;
|
||||
return inner.map((ih) => String(ih['command'] ?? ''));
|
||||
});
|
||||
|
||||
for (const script of requiredPreToolUse) {
|
||||
if (!preCommands.some((c) => c.includes(script))) {
|
||||
warnings.push(`Missing PreToolUse hook: ${script}`);
|
||||
}
|
||||
}
|
||||
for (const script of requiredPostToolUse) {
|
||||
if (!postCommands.some((c) => c.includes(script))) {
|
||||
warnings.push(`Missing PostToolUse hook: ${script}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check required plugins
|
||||
const plugins = (settings['enabledPlugins'] ?? {}) as Record<string, boolean>;
|
||||
const requiredPlugins = ['feature-dev', 'pr-review-toolkit', 'code-review'];
|
||||
|
||||
for (const plugin of requiredPlugins) {
|
||||
const found = Object.keys(plugins).some((k) => k.startsWith(plugin) && plugins[k]);
|
||||
if (!found) {
|
||||
warnings.push(`Missing plugin: ${plugin}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check enableAllMcpTools
|
||||
if (!settings['enableAllMcpTools']) {
|
||||
warnings.push('enableAllMcpTools is not true — MCP tools may require per-tool approval');
|
||||
}
|
||||
|
||||
return { warnings };
|
||||
}
|
||||
|
||||
function printSettingsWarnings(audit: SettingsAudit): void {
|
||||
if (audit.warnings.length === 0) return;
|
||||
|
||||
console.log('\n[mosaic] Claude Code settings audit:');
|
||||
for (const w of audit.warnings) {
|
||||
console.log(` ⚠ ${w}`);
|
||||
}
|
||||
console.log(
|
||||
'[mosaic] Run: mosaic doctor — or see ~/.config/mosaic/runtime/claude/RUNTIME.md for required settings.\n',
|
||||
);
|
||||
}
|
||||
|
||||
function checkSequentialThinking(runtime: string): void {
|
||||
const checker = fwScript('mosaic-ensure-sequential-thinking');
|
||||
if (!existsSync(checker)) return; // Skip if checker doesn't exist
|
||||
@@ -407,6 +483,10 @@ function launchRuntime(runtime: RuntimeName, args: string[], yolo: boolean): nev
|
||||
|
||||
switch (runtime) {
|
||||
case 'claude': {
|
||||
// Audit Claude Code settings and warn about missing hooks/plugins
|
||||
const settingsAudit = auditClaudeSettings();
|
||||
printSettingsWarnings(settingsAudit);
|
||||
|
||||
const prompt = buildRuntimePrompt('claude');
|
||||
const cliArgs = yolo ? ['--dangerously-skip-permissions'] : [];
|
||||
cliArgs.push('--append-system-prompt', prompt);
|
||||
|
||||
Reference in New Issue
Block a user