Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
80 changes: 27 additions & 53 deletions .claude/hooks/session-start.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#!/usr/bin/env node
// SessionStart hook — emits a small situational preamble when a session begins.
// Stdout is injected into the session as additional context (per Claude Code hook spec).
// Keep output short: branch + ahead/behind + 5 recent commits + tasks/INDEX status if present.
// SessionStart hook — emit only current repo/skill context.

import { readFileSync, existsSync } from "node:fs";
import { existsSync } from "node:fs";
import { spawnSync } from "node:child_process";
import { resolve } from "node:path";

Expand All @@ -13,70 +11,46 @@ function sh(cmd, args, opts = {}) {
return (r.stdout || "").trim();
}

const workspaceRoot = "/home/sk/mdeai";
const cwd = process.cwd();
const inMdeapp = existsSync(resolve(workspaceRoot, "mdeapp/package.json"));

// Workspace itself is not a git repo (per CLAUDE.md); mdeapp/ may have a .git.
const mdeappGit = existsSync(resolve(workspaceRoot, "mdeapp/.git"));
const gitCwd = mdeappGit ? resolve(workspaceRoot, "mdeapp") : cwd;

const branch = sh("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: gitCwd }) || "(none)";
const log = sh("git", ["log", "--oneline", "-5", "--no-decorate"], { cwd: gitCwd });
const status = sh("git", ["status", "--porcelain"], { cwd: gitCwd });
const root = "/home/sk/mdeai";
const skillsRoot = resolve(root, ".claude/skills");
const branch = sh("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: root }) || "(none)";
const head = sh("git", ["rev-parse", "--short", "HEAD"], { cwd: root }) || "(none)";
const status = sh("git", ["status", "--porcelain"], { cwd: root });
const dirty = status ? `${status.split("\n").length} changed file(s)` : "clean";
const log = sh("git", ["log", "--oneline", "-3", "--no-decorate"], { cwd: root });

let tasksSection = "";
const tasksIndex = resolve(workspaceRoot, "tasks/INDEX.md");
if (existsSync(tasksIndex)) {
try {
const head = readFileSync(tasksIndex, "utf8").split("\n").slice(0, 25).join("\n");
tasksSection = `\n## tasks/INDEX.md (first 25 lines)\n\n${head}\n`;
} catch {
/* ignore */
}
}
const required = ["using-mde-skills", "tasks", "copilotkit", "mastra", "supabase", "gemini"];
const missing = required.filter((name) => !existsSync(resolve(skillsRoot, name, "SKILL.md")));
const broken = sh("bash", ["-lc", `find "${skillsRoot}" -maxdepth 1 -type l ! -exec test -e {} \\; -print 2>/dev/null | sed 's#^.*/##'`]);
const brokenList = broken ? broken.split("\n").filter(Boolean) : [];

const reminders = [
"Phase 1, Week 1. App: mdeapp/. CopilotKit pinned at 1.55.2. Gemini model: gemini-3.5-flash.",
"Hard rules: no service-role keys in mdeapp/src/**; RLS + ≥1 policy on every new table; X-Goog-FieldMask on every Places call; mapId on every Map; CopilotKit v2 /v2 subpath imports only (no bare v1 @copilotkit/react-core).",
"Legacy /home/sk/mde/ is read-only reference. Do not edit it.",
];

let skillsSection = "";
const agentsLink = resolve(workspaceRoot, ".agents/skills/copilotkit/SKILL.md");
const brokenSkills = sh("bash", ["-c", `find "${resolve(workspaceRoot, ".claude/skills")}" -maxdepth 1 -type l ! -exec test -e {} \\; -print 2>/dev/null | head -3`]);
const verifyHint = "ln -sf .claude/agents/.agents .agents && ./scripts/verify-skills.sh --manifest";
if (!existsSync(agentsLink)) {
skillsSection = `\n## ⚠ Skills integrity\n\n- **FAIL:** \`.agents\` broken. Restore: \`${verifyHint}\`\n`;
} else if (brokenSkills) {
skillsSection = `\n## ⚠ Skills integrity\n\n- Broken symlinks: \`${brokenSkills.split("\n").join("`, `")}\`\n- Run: \`${verifyHint}\`\n`;
} else {
const topicInScan = sh("bash", ["-c", `for s in copilotkit-develop ui-ux-pro-max 21st-dev-builder-v2; do test -e "${resolve(workspaceRoot, ".claude/skills")}/$s" && echo $s; done | head -3`]);
if (topicInScan) {
skillsSection = `\n## ⚠ Skills scan root\n\n- Topic-only skills in scan (prune): \`${topicInScan.split("\n").join("`, `")}\`\n- Run: \`./scripts/prune-scan-root.sh\`\n`;
} else {
skillsSection = `\n## Skills\n\n- Scan root OK (Phase 1 default) · \`./scripts/verify-skills.sh --manifest\`\n`;
}
}
const skillStatus = missing.length === 0 && brokenList.length === 0
? "canonical skill scan: OK"
: `skill scan needs attention: missing=${missing.join(",") || "none"}; broken=${brokenList.join(",") || "none"}`;

const out = `# Session preamble

- Branch (mdeapp): \`${branch}\`
- Repo: /home/sk/mdeai
- Branch: ${branch}
- HEAD: ${head}
- Working tree: ${dirty}
- mdeapp present: ${inMdeapp ? "yes" : "no"}
- ${skillStatus}

## Recent commits

\`\`\`
${log || "(no commits)"}
\`\`\`
${tasksSection}${skillsSection}
## Reminders

${reminders.map((r) => `- ${r}`).join("\n")}
## Skill flow

Use \`mde-task-lifecycle\` to plan/ship a task. Floor before shipping: \`/verify-floor\`.
- Simple task → use the directly relevant skill.
- Ambiguous/multi-system task → \`using-mde-skills\`.
- Substantial implementation → \`tasks\`.
- Failure with unknown cause → \`systematic-debugging\`.
- Existing diff/PR → \`code-review\`.
- Done/merge/production claim → \`task-verifier\`.
- \`mde-task-lifecycle\` is retired.
`;

process.stdout.write(out);
Expand Down
87 changes: 33 additions & 54 deletions .claude/skills/_template/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,53 @@
---
name: mde-EXAMPLE
name: example-skill
description: >-
Use when a concrete set of trigger conditions for this skill applies.
disable-model-invocation: true
description: TEMPLATE — not a real skill. Copy this folder to `.claude/skills/mde-<domain>/` and remove `disable-model-invocation`. One-line WHAT + WHEN + at least 6 trigger phrases users would actually say. Trigger when the user says "phrase A", "phrase B", "phrase C", "phrase D", "phrase E", or "phrase F". Does NOT handle <out-of-scope topic 1> (use <other-skill>) or <out-of-scope topic 2> (use <other-skill>). Replaces the legacy skills <list>.
---

# mde-EXAMPLE — superskill template
# Example skill template

> Copy this folder to `.claude/skills/mde-<domain>/` and fill in the four sections below. Keep this file ≤300 lines (PDF best practice: SKILL.md under 5,000 words). Move deep how-to to `references/`.
> Copy this folder to `.claude/skills/<skill-name>/`. Keep the active `SKILL.md` concise and move deep material to `references/`.

---
## Ownership

## When to invoke
State the exact responsibility this skill owns and the neighboring concerns it does not own.

| Trigger phrase | Action |
|----------------|--------|
| "<obvious phrase 1>" | Route to `<topic-1>.md` |
| "<obvious phrase 2>" | Route to `<topic-2>.md` |
| "<paraphrased phrase>" | Route via decision tree below |
## Source priority

### Don't invoke for
1. Current runtime/repository evidence.
2. Version-matched official source or docs.
3. MDE-specific invariants.
4. Historical/reference material.

- <Anti-trigger 1> → `<sibling-skill>`
- <Anti-trigger 2> → `<sibling-skill>`
## When to use

---
List concrete symptoms, intents, technologies, and situations that make this skill relevant.
Keep workflow instructions out of the frontmatter description.

## Sub-modules at a glance
## Boundaries

| Module | Purpose | Specialist used |
|--------|---------|-----------------|
| [topic-1.md](topic-1.md) | <one line> | (none) |
| [topic-2.md](topic-2.md) | <one line> | <other-skill> |
| [topic-3.md](topic-3.md) | <one line> | (none) |
Explain important exclusions and route them to the correct neighboring skill when useful.
## Decision rules

---
Put the reusable judgment here. Use imperative instructions and explain why important constraints exist.
Keep volatile API details out of the main skill when they can be looked up or isolated in references.

## Routing decision tree
## Workflow

```
User intent
│
├─ <decision 1>?
│ ├─ Yes → topic-1.md
│ └─ No → continue
│
├─ <decision 2>?
│ ├─ Yes → topic-2.md
│ └─ No → topic-3.md
```
1. Inspect the current state before changing anything.
2. Load only the reference needed for the current variant/problem.
3. Make the smallest safe change consistent with the owning contract.
4. Verify the affected behavior with objective evidence.
5. Hand off to independent review/verification when risk requires it.

---
## References

## Quick links

| Resource | Path |
|----------|------|
| Module 1 | [topic-1.md](topic-1.md) |
| Module 2 | [topic-2.md](topic-2.md) |
| Module 3 | [topic-3.md](topic-3.md) |
| Deep reference | [references/<topic>.md](references/<topic>.md) |

---
- `references/<topic>.md` — explain exactly when to read it.
- `scripts/<helper>` — use for deterministic/repetitive checks.
- `assets/<asset>` — use only when producing the related output.

## Author checklist (delete before commit)
## Evaluation

- [ ] `name:` is kebab-case, ≤64 chars, no `claude` / `anthropic`
- [ ] `description:` ≤1024 chars, includes WHAT + WHEN + 6+ trigger phrases + negative triggers
- [ ] SKILL.md body ≤300 lines (1k–1.5k tokens loaded when triggered)
- [ ] All deep how-to moved to `references/<topic>.md`
- [ ] No `README.md` inside this folder (forbidden by spec)
- [ ] PDF p.15 trigger test: 3 obvious + 3 paraphrased fire; 3 unrelated do NOT fire
- [ ] Each sub-module has clear entry/exit and routes back to SKILL.md or onward
- [ ] Originals soft-deprecated (`DEPRECATED <date> — superseded by mde-<domain>`) and `disable-model-invocation: true`
Keep trigger evals separate from behavior evals.
For material rewrites, compare the candidate against a no-skill or previous-skill baseline when the behavior is objectively testable.
33 changes: 33 additions & 0 deletions .claude/skills/cloudinary/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: cloudinary
description: >-
Use when MDE work explicitly introduces or changes Cloudinary uploads, assets, transformations, delivery URLs, signatures, webhooks, or media lifecycle behavior.
---

# Cloudinary

Own Cloudinary-specific media behavior. Do not assume Cloudinary is active merely because the project may use media assets.

## Current-state rule

The current repo has no direct Cloudinary dependency or active source reference in the audited application paths. First verify that the task actually uses Cloudinary. If not, do not introduce it as architecture by default.

## Invariants

- Keep API secrets and signing secrets server-side.
- Prefer signed uploads/transformations when the operation requires trust.
- Validate resource ownership before destructive asset changes.
- Keep durable application metadata in the application database; Cloudinary is media infrastructure, not the business source of truth.
- Verify webhook signatures before applying side effects.

## Workflow

1. Confirm Cloudinary is in scope and inspect any existing integration.
2. Verify the current official API/SDK contract.
3. Define upload, transformation, deletion, and failure behavior.
4. Implement only the required integration surface.
5. Test invalid signatures, missing assets, and retry behavior when applicable.

## Handoff

Use `nextjs` for framework upload routes, `supabase` for application metadata/authorization, and the owning domain skill for product behavior.
32 changes: 32 additions & 0 deletions .claude/skills/cloudinary/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"version": 1,
"evals": [
{
"prompt": "Handle a focused cloudinary change in MDE and identify the correct implementation boundary.",
"expected_output": "Uses cloudinary as the primary specialist and keeps unrelated domains out.",
"expectations": [
"inspects current repo state",
"uses current official docs for version-sensitive behavior",
"makes the smallest safe change"
]
},
{
"prompt": "A bug appears near cloudinary, but the root cause is not known. What owns diagnosis?",
"expected_output": "Routes diagnosis to systematic-debugging while retaining the specialist for domain evidence.",
"expectations": [
"does not guess root cause",
"uses systematic-debugging for diagnosis",
"keeps specialist scope bounded"
]
},
{
"prompt": "A production-critical cloudinary change is ready to ship. What proof is required?",
"expected_output": "Requires targeted tests and independent task verification before Done.",
"expectations": [
"requires current evidence",
"does not self-certify",
"uses task-verifier for completion proof"
]
}
]
}
1 change: 0 additions & 1 deletion .claude/skills/code-review

This file was deleted.

68 changes: 68 additions & 0 deletions .claude/skills/code-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
name: code-review
description: >-
Use when reviewing an existing PR, branch, commit range, or work-in-progress diff for correctness, regressions, security, maintainability, or spec fit.
context: fork
---

# Code Review

## Purpose

Review the actual diff against both the repository contract and the task/spec. Findings are hypotheses until proven against the exact current head.

## Ownership

`code-review` reviews implementation quality and spec fit. `task-verifier` independently decides whether the task/PR is actually complete and production-safe. Do not duplicate the verifier's full release gate here.

## Review inputs

Resolve before reviewing:
- exact head SHA;
- base/fixed point (`main`, merge-base, or user-supplied SHA);
- Linear task/spec and acceptance criteria when available;
- changed files plus relevant surrounding code;
- repository instructions (`AGENTS.md`, `CLAUDE.md`, domain skills);
- current tests/CI for the same head.

If the fixed point is ambiguous, use the PR merge-base when reviewing a PR; otherwise state the comparison chosen.

## Two-axis review

### 1. Spec fit

Map each acceptance criterion to code/tests/evidence. Flag missing behavior, invented scope, stale assumptions, broken migrations, unhandled states, or implementation that technically exists but does not produce the requested user outcome.

### 2. Code quality

Review only material risks:
- correctness and edge cases;
- auth/RLS/tenant boundaries;
- data integrity, retries, concurrency, idempotency;
- error/loading/empty/recovery behavior;
- duplicated or shallow abstractions;
- maintainability and naming;
- performance regressions;
- dependency/config/workflow risk;
- missing tests at the correct seam.

Do not report style trivia already handled by formatters/linters unless it changes meaning.

## Finding format

For every actionable finding provide:

```text
Severity: HIGH | MEDIUM | LOW
Category: correctness | security | data | reliability | architecture | test-gap | maintainability | performance
Evidence: file:line + exact behavior
Why it matters: concrete failure/user impact
Smallest safe fix: bounded recommendation
Verification: exact test/probe that proves the fix
```

Use `NOISE` when a reviewer/bot comment is disproven by current-head evidence.

## MDE rule

Prefer the smallest safe change. Do not use review as permission to redesign unrelated modules, add speculative abstractions, or create extra PRs for fixes/evidence that belong in the current task PR.
17 changes: 17 additions & 0 deletions .claude/skills/code-review/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"skill_name": "code-review",
"evals": [
{
"id": 1,
"prompt": "Review this branch against main and SAN-123.",
"expected_output": "Pin merge-base/head, review spec fit and code quality, and cite current-head findings.",
"files": []
},
{
"id": 2,
"prompt": "CodeRabbit says this line is a blocker. Fix it.",
"expected_output": "Verify the bot claim against exact-head code before applying or dismissing it.",
"files": []
}
]
}
Loading
Loading