diff --git a/.claude/settings.json b/.claude/settings.json index cf66f4619..e0334088d 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -78,5 +78,9 @@ } } }, - "enabledPlugins": {} -} \ No newline at end of file + "enabledPlugins": {}, + "env": { + "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1" + }, + "teammateMode": "in-process" +} diff --git a/.gitignore b/.gitignore index e8b9f455d..1f5b506ea 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,9 @@ Desktop.ini .notes +# Claude Code — workspace state, worktrees +.claude/worktrees/ + # Private internal docs (audits, drafts, pre-launch notes) docs/internal/ diff --git a/.lenserfight/README.md b/.lenserfight/README.md index 382328285..8226bc46a 100644 --- a/.lenserfight/README.md +++ b/.lenserfight/README.md @@ -26,7 +26,7 @@ Use: ```bash lf validate lf validate --no-global -lf validate .lenserfight/colenses/pr-review/COLENS.MD +lf validate .lenserfight/colenses/pr-review/SKILL.md ``` Override behavior, highest priority first: @@ -59,37 +59,39 @@ Full docs: [`docs/lenserfight-file-system.md`](../docs/lenserfight-file-system.m ``` .lenserfight/ ├── README.md ← this file -├── lenses/ ← LENS.MD (and SKILL.MD alias) per lens template +├── lenses/ ← SKILL.md per lens template │ └── / -│ ├── LENS.MD ← canonical, ConectLens-native form -│ ├── SKILL.MD ← optional industry-compatibility alias +│ ├── SKILL.md ← agentskills.io-standard filename │ ├── references/ ← supporting prompt fragments, examples │ ├── assets/ ← non-secret static assets │ ├── templates/ ← parameter placeholder examples │ └── scripts/ ← optional generator/test scripts -├── lensers/ ← LENSER.MD per lenser template -│ └── /LENSER.MD -├── colenses/ ← COLENS.MD per colens template -│ └── /COLENS.MD -├── battles/ ← BATTLE.MD per battle template -│ └── /BATTLE.MD -└── rays/ ← RAY.MD per canonical production ray - └── /RAY.MD +├── lensers/ ← SKILL.md per lenser template +│ └── /SKILL.md +├── colenses/ ← SKILL.md per colens template +│ └── /SKILL.md +├── battles/ ← SKILL.md per battle template +│ └── /SKILL.md +├── rays/ ← SKILL.md per canonical production ray +│ └── /SKILL.md +└── skills/ ← SKILL.md per agent skill (Claude Code, lf CLI) + └── /SKILL.md ``` ## Core terminology -LenserFight is part of the **ConectLens** ecosystem. The platform uses native terminology in `.MD` filenames so the on-disk vocabulary matches the runtime database: +LenserFight follows the **agentskills.io** sector standard. Every item is a Skill — the `SKILL.md` filename is universal; the directory name determines the kind: -| File | Concept | DB table | -| ------------ | ------------------------------------------------------------ | --------------------- | -| `LENS.MD` | A reusable prompt asset — a single AI instruction unit | `lenses.lenses` | -| `LENSER.MD` | A person or AI profile that owns lenses and execution policy | `lensers.profiles`, `agents.ai_lensers` | -| `COLENS.MD` | A DAG of lens nodes feeding outputs into each other | `lenses.workflows` | -| `BATTLE.MD` | A scored competition between contenders | `battles.battles` | -| `RAY.MD` | A discovery ray (`/ray/:slug` route) | `content.tags` | +| Directory | Kind | Concept | DB table | +| ------------ | ------- | ------------------------------------------------------------ | --------------------- | +| `lenses/` | Lens | A reusable prompt asset — a single AI instruction unit | `lenses.lenses` | +| `lensers/` | Lenser | An AI profile that owns lenses and execution policy | `lensers.profiles`, `agents.ai_lensers` | +| `colenses/` | CoLens | A DAG of lens nodes feeding outputs into each other | `lenses.workflows` | +| `battles/` | Battle | A scored competition between contenders | `battles.battles` | +| `rays/` | Ray | A discovery ray (`/ray/:slug` route) | `content.tags` | +| `skills/` | Skill | An agent skill (CLI, IDE, agentic use) | — | -`SKILL.MD` is supported as an industry-compatibility alias for `LENS.MD` — many OSS AI ecosystems use `SKILL.MD` for the same concept. Legacy `agents/AGENT.MD` and `workflows/WORKFLOW.MD` are read for compatibility only; canonical files are `lensers/LENSER.MD` and `colenses/COLENS.MD`. +Legacy `agents/AGENT.MD` and `workflows/WORKFLOW.MD` are read for compatibility only. ## What MUST NOT live here @@ -119,47 +121,54 @@ The seed file is the source of truth for the database row; the `.MD` file is the ## Authoring a new template 1. Pick a slug — lowercase, hyphenated, ≤ 40 chars (matches `content.tags.slug` rules). -2. Create `.lenserfight/lenses//LENS.MD` with the frontmatter schema below. +2. Create `.lenserfight/lenses//SKILL.md` with the frontmatter schema below. 3. Add the corresponding SQL block to the matching seed file under `supabase/seeds/4*_*templates.sql`. -4. Add rays via `.lenserfight/rays//RAY.MD` if you introduce a new one. +4. Add rays via `.lenserfight/rays//SKILL.md` if you introduce a new one. 5. Run `pnpm supabase:combine-seeds && pnpm supabase:reset` locally and confirm the lens page loads. -### `LENS.MD` frontmatter schema +### `SKILL.md` frontmatter schema (agentskills.io standard) ```yaml --- name: -title: -description: -author: '@lenserfight' | '@chainabit' | '@conectlens' -visibility: public | unlisted | private -forkable: true | false -disclaimer: -inputs: - - label: - tool: text | textarea - required: true | false - example: -outputs: - kind: text | image | video | audio | table | checklist | script | structured -tags: - - -seed_uuid: +description: --- ``` -The body of `LENS.MD` is the actual prompt template using `[[param_label]]` for parameter substitution. +Two fields only. The body is the prompt template; use `[[param_label]]` tokens for parameter substitution. + +**LenserFight extensions** go in the body as markdown sections, not in frontmatter: +- Parameters: list `[[label]]` tokens under a `## Parameters` heading with descriptions. +- Legal disclaimers: add a `> **Disclaimer:** This output is not legal/financial advice.` blockquote. + +### Example + +```markdown +--- +name: code-reviewer +description: Review a diff for correctness, security, tests, maintainability, and release risk. Use when reviewing PRs or patches. +--- + +# Code Reviewer + +Review `[[diff]]` using `[[context]]` when provided. + +## Parameters + +- `[[diff]]` — the unified diff to review (required) +- `[[context]]` — additional context such as ticket description or prior review comments (optional) +``` ## Conventions to remember - Slugs are stable. Renaming a slug breaks every `/ray/` link and every published share URL. - UUIDs in seeds are stable. Never change a seed UUID once it has shipped. -- The `disclaimer:` field is mandatory for any template that touches legal or financial advice. Tests fail if it is missing on a tagged-`legal` or tagged-`finance` lens. -- `forkable: true` requires that the template can produce a clean clone via `fn_create_lens` / `fn_clone_workflow` / `fn_battles_create_rematch`. -- The first non-frontmatter heading of every `.MD` file should be `# ` matching the frontmatter `title:`. +- Legal/finance templates must include a disclaimer in the body (not frontmatter). Tests fail if it is missing. +- The kind is inferred from the directory (`lenses/` → Lens, `battles/` → Battle, etc.), not from frontmatter. +- The first non-frontmatter heading of every `SKILL.md` should be `# <Human Title>`. ## Related docs - [`docs/en/reference/storage-architecture.md`](../docs/en/reference/storage-architecture.md) — project vs. runtime separation rules -- [`docs/en/how-to/contributors/template-authoring.md`](../docs/en/how-to/contributors/template-authoring.md) — how to write a `LENS.MD` +- [`docs/en/how-to/contributors/template-authoring.md`](../docs/en/how-to/contributors/template-authoring.md) — how to write a `SKILL.md` - [`docs/en/reference/community-api/ai-lensers.md`](../docs/en/reference/community-api/ai-lensers.md) — agent API diff --git a/.lenserfight/battles/blog-vs-youtube-content/BATTLE.MD b/.lenserfight/battles/blog-vs-youtube-content/SKILL.md similarity index 67% rename from .lenserfight/battles/blog-vs-youtube-content/BATTLE.MD rename to .lenserfight/battles/blog-vs-youtube-content/SKILL.md index 901133cd8..d96a18b3b 100644 --- a/.lenserfight/battles/blog-vs-youtube-content/BATTLE.MD +++ b/.lenserfight/battles/blog-vs-youtube-content/SKILL.md @@ -1,21 +1,6 @@ --- name: blog-vs-youtube-content -title: Blog vs YouTube — Same Topic, Different Medium description: Creator-side battle comparing the blog outline and YouTube script for the same topic. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: workflow -contenders: - - kind: colens - workflow: blog-writer - label: Blog Writer - - kind: lens - lens: youtube-script-generator - label: YouTube Script Generator -voter_eligibility: open -rays: [content, creator, blog, youtube, template] -seed_uuid: 51000000-0002-0005-0000-000000000001 --- # Blog vs YouTube — Same Topic, Different Medium diff --git a/.lenserfight/battles/claude-vs-openai-pr-review/BATTLE.MD b/.lenserfight/battles/claude-vs-openai-pr-review/SKILL.md similarity index 73% rename from .lenserfight/battles/claude-vs-openai-pr-review/BATTLE.MD rename to .lenserfight/battles/claude-vs-openai-pr-review/SKILL.md index 3b87097f3..8e480f959 100644 --- a/.lenserfight/battles/claude-vs-openai-pr-review/BATTLE.MD +++ b/.lenserfight/battles/claude-vs-openai-pr-review/SKILL.md @@ -1,23 +1,6 @@ --- name: claude-vs-openai-pr-review -title: Claude vs OpenAI — Pull Request Review description: Battle template comparing Claude and OpenAI on the same code review task using a four-axis rubric. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: lens -lens: code-reviewer -rubric: code-quality-rubric -contenders: - - kind: ai_model - model: claude-sonnet-4-6 - label: Claude Sonnet 4.6 - - kind: ai_model - model: gpt-4o - label: GPT-4o -voter_eligibility: open -rays: [github, claude, openai, developer, template] -seed_uuid: 51000000-0002-0004-0000-000000000001 --- # Claude vs OpenAI — Pull Request Review diff --git a/.lenserfight/battles/finance-report-workflow-comparison/BATTLE.MD b/.lenserfight/battles/finance-report-workflow-comparison/SKILL.md similarity index 57% rename from .lenserfight/battles/finance-report-workflow-comparison/BATTLE.MD rename to .lenserfight/battles/finance-report-workflow-comparison/SKILL.md index ecb1b461c..2cd7ba629 100644 --- a/.lenserfight/battles/finance-report-workflow-comparison/BATTLE.MD +++ b/.lenserfight/battles/finance-report-workflow-comparison/SKILL.md @@ -1,18 +1,6 @@ --- name: finance-report-workflow-comparison -title: Finance Report Workflow Comparison description: Compares single-lens and workflow-based finance report explanations. This is not financial advice. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: workflow -participants: - - type: workflow - ref: finance-report-review - - type: lens - ref: finance-report-explainer -rubric: finance-explanation-rubric -rays: [finance, business, ai-comparison] --- # Finance Report Workflow Comparison diff --git a/.lenserfight/battles/gemini-vs-openai-youtube-planning/BATTLE.MD b/.lenserfight/battles/gemini-vs-openai-youtube-planning/BATTLE.MD deleted file mode 100644 index af86679b1..000000000 --- a/.lenserfight/battles/gemini-vs-openai-youtube-planning/BATTLE.MD +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: gemini-vs-openai-youtube-planning -title: Gemini vs OpenAI — YouTube Planning -description: Compares two models on creator planning using the YouTube content workflow. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: workflow -participants: - - type: workflow - ref: youtube-content -contenders: - - kind: ai_model - model: gemini-2.5-flash - label: Gemini 2.5 Flash - - kind: ai_model - model: gpt-5 - label: GPT-5 -rubric: creator-production-rubric -voter_eligibility: open -rays: [creator, youtube, gemini, openai, ai-comparison] ---- - -# Gemini vs OpenAI — YouTube Planning - -This battle compares how two models turn the same video brief into script, storyboard, thumbnail, and repurposing outputs. - -## Evaluation - -Score usefulness, audience fit, production specificity, factual discipline, and channel readiness. diff --git a/.lenserfight/battles/gemini-vs-openai-youtube-planning/SKILL.md b/.lenserfight/battles/gemini-vs-openai-youtube-planning/SKILL.md new file mode 100644 index 000000000..99c886fcf --- /dev/null +++ b/.lenserfight/battles/gemini-vs-openai-youtube-planning/SKILL.md @@ -0,0 +1,12 @@ +--- +name: gemini-vs-openai-youtube-planning +description: Compares two models on creator planning using the YouTube content workflow. +--- + +# Gemini vs OpenAI — YouTube Planning + +This battle compares how two models turn the same video brief into script, storyboard, thumbnail, and repurposing outputs. + +## Evaluation + +Score usefulness, audience fit, production specificity, factual discipline, and channel readiness. diff --git a/.lenserfight/battles/legal-review-comparison/BATTLE.MD b/.lenserfight/battles/legal-review-comparison/SKILL.md similarity index 63% rename from .lenserfight/battles/legal-review-comparison/BATTLE.MD rename to .lenserfight/battles/legal-review-comparison/SKILL.md index 974f6f664..7d5f2e01e 100644 --- a/.lenserfight/battles/legal-review-comparison/BATTLE.MD +++ b/.lenserfight/battles/legal-review-comparison/SKILL.md @@ -1,26 +1,6 @@ --- name: legal-review-comparison -title: Legal Review — Claude vs Gemini on the Same Contract description: Battle template comparing AI legal-review outputs on identical contract text. Analysis only — NOT legal advice. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: lens -lens: legal-contract-reviewer -disclaimer: | - Outputs in this battle are analysis aids and NOT legal advice. The battle - outcome does not validate any model as fit for legal practice. Always have a - qualified, licensed lawyer review the actual document before acting. -contenders: - - kind: ai_model - model: claude-sonnet-4-6 - label: Claude Sonnet 4.6 - - kind: ai_model - model: gemini-2.5-flash - label: Gemini 2.5 Flash -voter_eligibility: open -rays: [legal, claude, gemini, analysis, template] -seed_uuid: 51000000-0002-0006-0000-000000000001 --- # Legal Review — Claude vs Gemini diff --git a/.lenserfight/battles/legal-workflow-comparison/BATTLE.MD b/.lenserfight/battles/legal-workflow-comparison/SKILL.md similarity index 63% rename from .lenserfight/battles/legal-workflow-comparison/BATTLE.MD rename to .lenserfight/battles/legal-workflow-comparison/SKILL.md index 401b41f72..902303548 100644 --- a/.lenserfight/battles/legal-workflow-comparison/BATTLE.MD +++ b/.lenserfight/battles/legal-workflow-comparison/SKILL.md @@ -1,18 +1,6 @@ --- name: legal-workflow-comparison -title: Legal Workflow Comparison description: Compares legal-adjacent document review outputs. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: workflow -participants: - - type: workflow - ref: legal-document-review - - type: lens - ref: legal-contract-reviewer -rubric: legal-triage-rubric -rays: [legal, ai-comparison] --- # Legal Workflow Comparison diff --git a/.lenserfight/battles/reasoning-quality-shootout/BATTLE.MD b/.lenserfight/battles/reasoning-quality-shootout/BATTLE.MD deleted file mode 100644 index 29b3495f7..000000000 --- a/.lenserfight/battles/reasoning-quality-shootout/BATTLE.MD +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: reasoning-quality-shootout -title: Reasoning Quality Shootout -description: Compares model answers with an explicit reasoning-quality scorecard. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: lens -participants: - - type: lens - ref: reasoning-quality-comparison -contenders: - - kind: ai_model - model: claude-sonnet-4-6 - label: Claude Sonnet 4.6 - - kind: ai_model - model: gpt-5 - label: GPT-5 - - kind: ai_model - model: gemini-2.5-flash - label: Gemini 2.5 Flash -rubric: reasoning-quality-rubric -rays: [ai-comparison, claude, openai, gemini] ---- - -# Reasoning Quality Shootout - -Use this battle when a team wants to compare reasoning quality rather than style. - -## Evaluation - -Judge evidence use, assumptions, edge cases, calibration, and decision usefulness. diff --git a/.lenserfight/battles/reasoning-quality-shootout/SKILL.md b/.lenserfight/battles/reasoning-quality-shootout/SKILL.md new file mode 100644 index 000000000..f194806c4 --- /dev/null +++ b/.lenserfight/battles/reasoning-quality-shootout/SKILL.md @@ -0,0 +1,12 @@ +--- +name: reasoning-quality-shootout +description: Compares model answers with an explicit reasoning-quality scorecard. +--- + +# Reasoning Quality Shootout + +Use this battle when a team wants to compare reasoning quality rather than style. + +## Evaluation + +Judge evidence use, assumptions, edge cases, calibration, and decision usefulness. diff --git a/.lenserfight/battles/workflow-vs-lens-pr-review/BATTLE.MD b/.lenserfight/battles/workflow-vs-lens-pr-review/SKILL.md similarity index 59% rename from .lenserfight/battles/workflow-vs-lens-pr-review/BATTLE.MD rename to .lenserfight/battles/workflow-vs-lens-pr-review/SKILL.md index 88895c79f..b5963e653 100644 --- a/.lenserfight/battles/workflow-vs-lens-pr-review/BATTLE.MD +++ b/.lenserfight/battles/workflow-vs-lens-pr-review/SKILL.md @@ -1,18 +1,6 @@ --- name: workflow-vs-lens-pr-review -title: Workflow vs Lens — PR Review description: Compares a single code-review lens against a multi-step PR review workflow. -author: '@lenserfight' -visibility: public -forkable: true -battle_type: workflow -participants: - - type: lens - ref: code-reviewer - - type: workflow - ref: pr-review -rubric: pr-review-depth-rubric -rays: [developer, github, ai-comparison] --- # Workflow vs Lens — PR Review diff --git a/.lenserfight/colenses/ai-model-comparison/COLENS.MD b/.lenserfight/colenses/ai-model-comparison/COLENS.MD deleted file mode 100644 index 1cbc71c6f..000000000 --- a/.lenserfight/colenses/ai-model-comparison/COLENS.MD +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: ai-model-comparison -title: AI Model Comparison Colens -description: Compare model outputs using output comparison, reasoning quality, and a judge lenser. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: compare - lens: ai-output-comparator - - id: reasoning - lens: reasoning-quality-comparison - inputs_from: compare - - id: judge - lenser: evaluation-judge - inputs_from: reasoning -outputs: - kind: scorecard -rays: [ai-comparison, openai, claude, gemini, colens] ---- - -# AI Model Comparison Colens - -Use when multiple model outputs need a transparent rubric and repeatable judgment. diff --git a/.lenserfight/colenses/ai-model-comparison/SKILL.md b/.lenserfight/colenses/ai-model-comparison/SKILL.md new file mode 100644 index 000000000..ec1342912 --- /dev/null +++ b/.lenserfight/colenses/ai-model-comparison/SKILL.md @@ -0,0 +1,8 @@ +--- +name: ai-model-comparison +description: Compare model outputs using output comparison, reasoning quality, and a judge lenser. +--- + +# AI Model Comparison Colens + +Use when multiple model outputs need a transparent rubric and repeatable judgment. diff --git a/.lenserfight/colenses/blog-writer/COLENS.MD b/.lenserfight/colenses/blog-writer/SKILL.md similarity index 66% rename from .lenserfight/colenses/blog-writer/COLENS.MD rename to .lenserfight/colenses/blog-writer/SKILL.md index 320725fd7..1330f5c72 100644 --- a/.lenserfight/colenses/blog-writer/COLENS.MD +++ b/.lenserfight/colenses/blog-writer/SKILL.md @@ -1,28 +1,6 @@ --- name: blog-writer -title: Blog Writer Colens description: From topic to publishable draft — research, outline, draft, SEO metadata. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: research - lens: intent-clarifier - note: Refine the editorial brief and surface assumptions. - - id: outline - lens: blog-outline-generator - inputs_from: research - - id: image - lens: ai-image-prompt-builder - inputs_from: outline - note: Hero image prompt for the post header. - - id: validate - lens: validate-output - inputs_from: outline -outputs: - kind: text -rays: [blog, content, creator, colens, template] -seed_uuid: 48000000-0002-0002-0001-000000000001 --- # Blog Writer Colens diff --git a/.lenserfight/colenses/finance-report-review/COLENS.MD b/.lenserfight/colenses/finance-report-review/COLENS.MD deleted file mode 100644 index 472916066..000000000 --- a/.lenserfight/colenses/finance-report-review/COLENS.MD +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: finance-report-review -title: Finance Report Review Colens -description: Explain a finance report, review KPIs, and draft investor-facing notes. This is not financial advice. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: explain - lens: finance-report-explainer - - id: kpis - lens: kpi-reviewer - inputs_from: explain - - id: investor - lens: investor-update-drafter - inputs_from: kpis - - id: analyst - lenser: finance-analyst - inputs_from: investor -outputs: - kind: memo -rays: [finance, business, colens] ---- - -# Finance Report Review Colens - -Use when finance data needs to become an operator-ready memo. This is not financial advice. diff --git a/.lenserfight/colenses/finance-report-review/SKILL.md b/.lenserfight/colenses/finance-report-review/SKILL.md new file mode 100644 index 000000000..a0128bf12 --- /dev/null +++ b/.lenserfight/colenses/finance-report-review/SKILL.md @@ -0,0 +1,8 @@ +--- +name: finance-report-review +description: Explain a finance report, review KPIs, and draft investor-facing notes. This is not financial advice. +--- + +# Finance Report Review Colens + +Use when finance data needs to become an operator-ready memo. This is not financial advice. diff --git a/.lenserfight/colenses/github-issue-solver/COLENS.MD b/.lenserfight/colenses/github-issue-solver/SKILL.md similarity index 64% rename from .lenserfight/colenses/github-issue-solver/COLENS.MD rename to .lenserfight/colenses/github-issue-solver/SKILL.md index d44afeaf9..5d2da353a 100644 --- a/.lenserfight/colenses/github-issue-solver/COLENS.MD +++ b/.lenserfight/colenses/github-issue-solver/SKILL.md @@ -1,33 +1,6 @@ --- name: github-issue-solver -title: GitHub Issue Solver Colens description: End-to-end issue resolution workflow — triage, root-cause analysis, GRASP-compliant fix design, test planning, and PR drafting in one pipeline. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: triage - lens: github-issue-triage - note: Classify the issue and determine priority before investing in a fix. - - id: analyze - lens: github-issue-solver - inputs_from: triage - note: Identify root cause, design GRASP-compliant fix, and produce implementation plan. - - id: tests - lens: unit-test-generator - inputs_from: analyze - note: Generate test cases that cover the root cause scenario and regression surface. - - id: review - lens: code-reviewer - inputs_from: analyze - note: Review the proposed implementation plan for correctness, security, and data risks before coding begins. - - id: pr - lens: pr-description-writer - inputs_from: review - note: Draft a complete PR description from the reviewed plan. -outputs: - kind: text -rays: [developer, github, colens, productivity] --- # GitHub Issue Solver Colens diff --git a/.lenserfight/colenses/github-issue-triage/COLENS.MD b/.lenserfight/colenses/github-issue-triage/COLENS.MD deleted file mode 100644 index 74649e807..000000000 --- a/.lenserfight/colenses/github-issue-triage/COLENS.MD +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: github-issue-triage -title: GitHub Issue Triage Colens -description: Classify issues, draft a response, and produce a maintainers' queue update. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: classify - lens: github-issue-triage - - id: prioritize - lens: task-prioritization - inputs_from: classify - - id: reviewer - lenser: developer-reviewer - inputs_from: prioritize -outputs: - kind: table -rays: [developer, github, colens] ---- - -# GitHub Issue Triage Colens - -Use this when a maintainer wants a deterministic issue queue: classify, prioritize, and draft the response a human can post. diff --git a/.lenserfight/colenses/github-issue-triage/SKILL.md b/.lenserfight/colenses/github-issue-triage/SKILL.md new file mode 100644 index 000000000..d4c766efb --- /dev/null +++ b/.lenserfight/colenses/github-issue-triage/SKILL.md @@ -0,0 +1,8 @@ +--- +name: github-issue-triage +description: Classify issues, draft a response, and produce a maintainers' queue update. +--- + +# GitHub Issue Triage Colens + +Use this when a maintainer wants a deterministic issue queue: classify, prioritize, and draft the response a human can post. diff --git a/.lenserfight/colenses/incident-postmortem/COLENS.MD b/.lenserfight/colenses/incident-postmortem/COLENS.MD deleted file mode 100644 index c20e6117c..000000000 --- a/.lenserfight/colenses/incident-postmortem/COLENS.MD +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: incident-postmortem -title: Incident Postmortem Colens -description: Build a blameless incident report and release follow-up tasks. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: postmortem - lens: incident-postmortem - - id: release-notes - lens: release-note-generator - inputs_from: postmortem - - id: review - lenser: developer-reviewer - inputs_from: release-notes -outputs: - kind: report -rays: [developer, operations, colens] ---- - -# Incident Postmortem Colens - -Use after an outage, regression, data issue, or failed launch. The colens turns notes into a postmortem and follow-up release notes. diff --git a/.lenserfight/colenses/incident-postmortem/SKILL.md b/.lenserfight/colenses/incident-postmortem/SKILL.md new file mode 100644 index 000000000..4bbe185f9 --- /dev/null +++ b/.lenserfight/colenses/incident-postmortem/SKILL.md @@ -0,0 +1,8 @@ +--- +name: incident-postmortem +description: Build a blameless incident report and release follow-up tasks. +--- + +# Incident Postmortem Colens + +Use after an outage, regression, data issue, or failed launch. The colens turns notes into a postmortem and follow-up release notes. diff --git a/.lenserfight/colenses/legal-document-review/COLENS.MD b/.lenserfight/colenses/legal-document-review/COLENS.MD deleted file mode 100644 index 800049008..000000000 --- a/.lenserfight/colenses/legal-document-review/COLENS.MD +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: legal-document-review -title: Legal Document Review Colens -description: Summarize a legal document, create a risk checklist, and prepare questions for counsel. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: summary - lens: contract-summary - - id: risks - lens: legal-risk-checklist - inputs_from: summary - - id: questions - lens: questions-for-lawyer - inputs_from: risks - - id: triage - lenser: legal-triage - inputs_from: questions -outputs: - kind: checklist -rays: [legal, colens, productivity] ---- - -# Legal Document Review Colens - -This colens helps prepare for a lawyer conversation. It is not legal advice and must be reviewed by a qualified lawyer. diff --git a/.lenserfight/colenses/legal-document-review/SKILL.md b/.lenserfight/colenses/legal-document-review/SKILL.md new file mode 100644 index 000000000..e09cf31ab --- /dev/null +++ b/.lenserfight/colenses/legal-document-review/SKILL.md @@ -0,0 +1,8 @@ +--- +name: legal-document-review +description: Summarize a legal document, create a risk checklist, and prepare questions for counsel. This is not legal advice and must be reviewed by a qualified lawyer. +--- + +# Legal Document Review Colens + +This colens helps prepare for a lawyer conversation. It is not legal advice and must be reviewed by a qualified lawyer. diff --git a/.lenserfight/colenses/pr-review/COLENS.MD b/.lenserfight/colenses/pr-review/SKILL.md similarity index 58% rename from .lenserfight/colenses/pr-review/COLENS.MD rename to .lenserfight/colenses/pr-review/SKILL.md index 4c1cd6b7f..84bed1c37 100644 --- a/.lenserfight/colenses/pr-review/COLENS.MD +++ b/.lenserfight/colenses/pr-review/SKILL.md @@ -1,28 +1,6 @@ --- name: pr-review -title: Pull Request Review Colens description: From diff to reviewer-ready summary — analyze, review, surface risks, draft PR description. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: triage - lens: pr-triage-brief - note: Where does this PR sit in the queue. - - id: review - lens: code-reviewer - inputs_from: triage - - id: tests - lens: unit-test-generator - inputs_from: review - note: Suggest test cases for behaviour the diff introduces. - - id: describe - lens: pr-description-writer - inputs_from: review -outputs: - kind: text -rays: [github, developer, colens, template] -seed_uuid: 48000000-0002-0006-0001-000000000001 --- # Pull Request Review Colens diff --git a/.lenserfight/colenses/release-readiness/COLENS.MD b/.lenserfight/colenses/release-readiness/COLENS.MD deleted file mode 100644 index 967f08973..000000000 --- a/.lenserfight/colenses/release-readiness/COLENS.MD +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: release-readiness -title: Release Readiness Colens -description: Review code risk, tests, release notes, and rollback before shipping. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: review - lens: code-reviewer - - id: tests - lens: unit-test-generator - inputs_from: review - - id: notes - lens: release-note-generator - inputs_from: review - - id: operator-check - lenser: developer-reviewer - inputs_from: notes -outputs: - kind: report -rays: [developer, operations, colens] ---- - -# Release Readiness Colens - -Run before a production-facing release. It produces merge risks, missing validation, release notes, and rollback notes. diff --git a/.lenserfight/colenses/release-readiness/SKILL.md b/.lenserfight/colenses/release-readiness/SKILL.md new file mode 100644 index 000000000..c0589def6 --- /dev/null +++ b/.lenserfight/colenses/release-readiness/SKILL.md @@ -0,0 +1,8 @@ +--- +name: release-readiness +description: Review code risk, tests, release notes, and rollback before shipping. +--- + +# Release Readiness Colens + +Run before a production-facing release. It produces merge risks, missing validation, release notes, and rollback notes. diff --git a/.lenserfight/colenses/startup-planning/COLENS.MD b/.lenserfight/colenses/startup-planning/SKILL.md similarity index 55% rename from .lenserfight/colenses/startup-planning/COLENS.MD rename to .lenserfight/colenses/startup-planning/SKILL.md index a6dbac8c8..b22829fd7 100644 --- a/.lenserfight/colenses/startup-planning/COLENS.MD +++ b/.lenserfight/colenses/startup-planning/SKILL.md @@ -1,25 +1,6 @@ --- name: startup-planning -title: Startup Planning Colens description: From idea to 12-week roadmap with deep-thinking checks and a weekly operating cadence. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: clarify - lens: deep-thinking-decision-helper - note: Stress-test the idea framing before committing to a roadmap. - - id: roadmap - lens: startup-roadmap-designer - inputs_from: clarify - - id: operating_cadence - lens: weekly-operating-review - inputs_from: roadmap - note: First-week operating review draft so the cadence is concrete from day one. -outputs: - kind: table -rays: [startup, planning, deep-thinking, colens, template] -seed_uuid: 48000000-0002-0007-0001-000000000001 --- # Startup Planning Colens diff --git a/.lenserfight/colenses/startup-weekly-operating-review/COLENS.MD b/.lenserfight/colenses/startup-weekly-operating-review/COLENS.MD deleted file mode 100644 index 0c2b60a52..000000000 --- a/.lenserfight/colenses/startup-weekly-operating-review/COLENS.MD +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: startup-weekly-operating-review -title: Startup Weekly Operating Review -description: Convert weekly startup notes into KPI review, founder decisions, launch risks, and next actions. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: founder-review - lens: founder-weekly-review - - id: kpis - lens: kpi-reviewer - inputs_from: founder-review - - id: decisions - lens: decision-memo - inputs_from: kpis - - id: operator - lenser: startup-operator - inputs_from: decisions -outputs: - kind: operating_review -rays: [startup, productivity, colens] ---- - -# Startup Weekly Operating Review - -Use for founder or leadership weekly reviews. It produces decisions, risks, owners, and next-week priorities. diff --git a/.lenserfight/colenses/startup-weekly-operating-review/SKILL.md b/.lenserfight/colenses/startup-weekly-operating-review/SKILL.md new file mode 100644 index 000000000..b1a4c8259 --- /dev/null +++ b/.lenserfight/colenses/startup-weekly-operating-review/SKILL.md @@ -0,0 +1,8 @@ +--- +name: startup-weekly-operating-review +description: Convert weekly startup notes into KPI review, founder decisions, launch risks, and next actions. +--- + +# Startup Weekly Operating Review + +Use for founder or leadership weekly reviews. It produces decisions, risks, owners, and next-week priorities. diff --git a/.lenserfight/colenses/youtube-content/COLENS.MD b/.lenserfight/colenses/youtube-content/COLENS.MD deleted file mode 100644 index 0de2ad3bf..000000000 --- a/.lenserfight/colenses/youtube-content/COLENS.MD +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: youtube-content -title: YouTube Content Colens -description: Plan a YouTube video from topic to script, storyboard, thumbnail, and short-form repurposing. -author: '@lenserfight' -visibility: public -forkable: true -nodes: - - id: script - lens: youtube-script-generator - - id: storyboard - lens: video-storyboard-planner - inputs_from: script - - id: thumbnail - lens: thumbnail-prompt-generator - inputs_from: script - - id: shorts - lens: short-form-video-repurposer - inputs_from: script - - id: producer - lenser: content-producer - inputs_from: storyboard -outputs: - kind: content_kit -rays: [creator, youtube, multimodal, colens] ---- - -# YouTube Content Colens - -Use for creator production: it turns a topic into a full script, visual plan, thumbnail prompts, and short-form clips. diff --git a/.lenserfight/colenses/youtube-content/SKILL.md b/.lenserfight/colenses/youtube-content/SKILL.md new file mode 100644 index 000000000..a58850cbb --- /dev/null +++ b/.lenserfight/colenses/youtube-content/SKILL.md @@ -0,0 +1,8 @@ +--- +name: youtube-content +description: Plan a YouTube video from topic to script, storyboard, thumbnail, and short-form repurposing. +--- + +# YouTube Content Colens + +Use for creator production: it turns a topic into a full script, visual plan, thumbnail prompts, and short-form clips. diff --git a/.lenserfight/lensers/ai-judge/LENSER.MD b/.lenserfight/lensers/ai-judge/SKILL.md similarity index 86% rename from .lenserfight/lensers/ai-judge/LENSER.MD rename to .lenserfight/lensers/ai-judge/SKILL.md index ac5084d5b..052ce6894 100644 --- a/.lenserfight/lensers/ai-judge/LENSER.MD +++ b/.lenserfight/lensers/ai-judge/SKILL.md @@ -1,14 +1,6 @@ --- name: ai-judge -title: AI Judge description: The neutral AI lenser that scores battle submissions when a battle is configured to use AI judging. -author: '@lenserfight' -visibility: public -agent_type: ai_judge -default_model: claude-sonnet-4-6 -fallback_models: [gpt-4o, gemini-2.5-flash] -personality: neutral_evaluator -rays: [ai, analysis, template] --- # AI Judge diff --git a/.lenserfight/lensers/chainabit-operator/LENSER.MD b/.lenserfight/lensers/chainabit-operator/SKILL.md similarity index 70% rename from .lenserfight/lensers/chainabit-operator/LENSER.MD rename to .lenserfight/lensers/chainabit-operator/SKILL.md index e98ae9e8a..f4aca2c9a 100644 --- a/.lenserfight/lensers/chainabit-operator/LENSER.MD +++ b/.lenserfight/lensers/chainabit-operator/SKILL.md @@ -1,14 +1,6 @@ --- name: chainabit-operator -title: Chainabit Operator description: The Chainabit-owned operator lenser that runs weekly reviews, async standups, PR triage, and launch content kits. -author: '@chainabit' -visibility: public -agent_type: ai_lenser -default_model: claude-sonnet-4-6 -fallback_models: [gpt-4o] -personality: practitioner -rays: [chainabit, productivity, operator] --- # Chainabit Operator @@ -25,11 +17,11 @@ The Chainabit Operator is the lenser that runs founder-style operating reviews a The Operator binds to: -- [`weekly-operating-review`](../../lenses/weekly-operating-review/LENS.MD) -- [`async-standup-generator`](../../lenses/async-standup-generator/LENS.MD) -- [`pr-triage-brief`](../../lenses/pr-triage-brief/LENS.MD) -- [`launch-content-kit`](../../lenses/launch-content-kit/LENS.MD) -- [`hiring-loop-designer`](../../lenses/hiring-loop-designer/LENS.MD) +- [`weekly-operating-review`](../../lenses/weekly-operating-review/SKILL.md) +- [`async-standup-generator`](../../lenses/async-standup-generator/SKILL.md) +- [`pr-triage-brief`](../../lenses/pr-triage-brief/SKILL.md) +- [`launch-content-kit`](../../lenses/launch-content-kit/SKILL.md) +- [`hiring-loop-designer`](../../lenses/hiring-loop-designer/SKILL.md) ## Memory profile diff --git a/.lenserfight/lensers/content-producer/LENSER.MD b/.lenserfight/lensers/content-producer/SKILL.md similarity index 78% rename from .lenserfight/lensers/content-producer/LENSER.MD rename to .lenserfight/lensers/content-producer/SKILL.md index 40bba14c8..210b9dc7d 100644 --- a/.lenserfight/lensers/content-producer/LENSER.MD +++ b/.lenserfight/lensers/content-producer/SKILL.md @@ -1,14 +1,6 @@ --- name: content-producer -title: Content Producer description: Converts briefs into blog, newsletter, video, short-form, and visual content packages. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -role: creator -capabilities: [editorial_planning, video_scripting, repurposing, visual_prompting] -rays: [creator, blog, youtube, multimodal] -version: 0.1.0 --- # Content Producer diff --git a/.lenserfight/lensers/developer-reviewer/LENSER.MD b/.lenserfight/lensers/developer-reviewer/SKILL.md similarity index 78% rename from .lenserfight/lensers/developer-reviewer/LENSER.MD rename to .lenserfight/lensers/developer-reviewer/SKILL.md index e4e3e9853..bf98259a3 100644 --- a/.lenserfight/lensers/developer-reviewer/LENSER.MD +++ b/.lenserfight/lensers/developer-reviewer/SKILL.md @@ -1,14 +1,6 @@ --- name: developer-reviewer -title: Developer Reviewer description: Senior engineering reviewer for diffs, API contracts, tests, migrations, and release risk. -author: '@lenserfight' -visibility: public -forkable: true -role: reviewer -capabilities: [code_review, test_planning, release_risk, api_contracts] -rays: [developer, github, productivity] -version: 0.1.0 --- # Developer Reviewer diff --git a/.lenserfight/lensers/evaluation-judge/LENSER.MD b/.lenserfight/lensers/evaluation-judge/SKILL.md similarity index 76% rename from .lenserfight/lensers/evaluation-judge/LENSER.MD rename to .lenserfight/lensers/evaluation-judge/SKILL.md index 603e19706..86679879c 100644 --- a/.lenserfight/lensers/evaluation-judge/LENSER.MD +++ b/.lenserfight/lensers/evaluation-judge/SKILL.md @@ -1,14 +1,6 @@ --- name: evaluation-judge -title: Evaluation Judge description: Scores competing AI, colens, or prompt outputs against a declared rubric with evidence. -author: '@lenserfight' -visibility: public -forkable: true -role: judge -capabilities: [rubric_scoring, battle_judging, output_comparison] -rays: [ai-comparison, openai, claude, gemini] -version: 0.1.0 --- # Evaluation Judge diff --git a/.lenserfight/lensers/finance-analyst/LENSER.MD b/.lenserfight/lensers/finance-analyst/SKILL.md similarity index 78% rename from .lenserfight/lensers/finance-analyst/LENSER.MD rename to .lenserfight/lensers/finance-analyst/SKILL.md index 0d1629e65..eb3f25b0c 100644 --- a/.lenserfight/lensers/finance-analyst/LENSER.MD +++ b/.lenserfight/lensers/finance-analyst/SKILL.md @@ -1,14 +1,6 @@ --- name: finance-analyst -title: Finance Analyst description: Explains financial reports, KPI movement, budget scenarios, and revenue experiments without pretending to provide certified advice. -author: '@lenserfight' -visibility: public -forkable: true -role: analyst -capabilities: [finance_explanation, kpi_review, budget_planning, revenue_experiments] -rays: [finance, business, startup] -version: 0.1.0 --- # Finance Analyst diff --git a/.lenserfight/lensers/issue-solver/LENSER.MD b/.lenserfight/lensers/issue-solver/SKILL.md similarity index 89% rename from .lenserfight/lensers/issue-solver/LENSER.MD rename to .lenserfight/lensers/issue-solver/SKILL.md index 175a53a5b..67257bc87 100644 --- a/.lenserfight/lensers/issue-solver/LENSER.MD +++ b/.lenserfight/lensers/issue-solver/SKILL.md @@ -1,14 +1,6 @@ --- name: issue-solver -title: Issue Solver description: Autonomous engineering agent that reads GitHub issues, traces root causes, designs GRASP-compliant fixes, runs tests, opens PRs, and closes issues only after merge. -author: '@lenserfight' -visibility: public -forkable: true -role: implementer -capabilities: [code_review, test_planning, git_operations, pr_creation, root_cause_analysis, migration_awareness] -rays: [developer, github, productivity] -version: 0.1.0 --- # Issue Solver diff --git a/.lenserfight/lensers/legal-triage/LENSER.MD b/.lenserfight/lensers/legal-triage/SKILL.md similarity index 77% rename from .lenserfight/lensers/legal-triage/LENSER.MD rename to .lenserfight/lensers/legal-triage/SKILL.md index 883b2f506..531abb437 100644 --- a/.lenserfight/lensers/legal-triage/LENSER.MD +++ b/.lenserfight/lensers/legal-triage/SKILL.md @@ -1,14 +1,6 @@ --- name: legal-triage -title: Legal Triage description: Legal-adjacent review assistant that summarizes documents, identifies risk questions, and routes issues to qualified counsel. -author: '@lenserfight' -visibility: public -forkable: true -role: triage -capabilities: [contract_summary, risk_checklist, counsel_questions, policy_comparison] -rays: [legal, legal-adjacent, productivity] -version: 0.1.0 --- # Legal Triage diff --git a/.lenserfight/lensers/lenserfight-author/LENSER.MD b/.lenserfight/lensers/lenserfight-author/SKILL.md similarity index 89% rename from .lenserfight/lensers/lenserfight-author/LENSER.MD rename to .lenserfight/lensers/lenserfight-author/SKILL.md index 41732e26a..68871234e 100644 --- a/.lenserfight/lensers/lenserfight-author/LENSER.MD +++ b/.lenserfight/lensers/lenserfight-author/SKILL.md @@ -1,14 +1,6 @@ --- name: lenserfight-author -title: LenserFight Template Author description: The canonical AI lenser that owns and revises every public LenserFight template. Personality is editor-first, opinionated. -author: '@lenserfight' -visibility: public -agent_type: ai_lenser -default_model: claude-sonnet-4-6 -fallback_models: [gpt-4o, gemini-2.5-flash] -personality: opinionated_editor -rays: [ai, template, content] --- # LenserFight Template Author diff --git a/.lenserfight/lensers/lenserfighter/LENSER.MD b/.lenserfight/lensers/lenserfighter/SKILL.md similarity index 92% rename from .lenserfight/lensers/lenserfighter/LENSER.MD rename to .lenserfight/lensers/lenserfighter/SKILL.md index 1929eb233..6b32c2a7f 100644 --- a/.lenserfight/lensers/lenserfighter/LENSER.MD +++ b/.lenserfight/lensers/lenserfighter/SKILL.md @@ -1,22 +1,6 @@ --- name: lenserfighter -title: LenserFighter description: Autonomous open-source contributor that reviews PRs, triages and opens issues, and drafts minimal fix PRs for the LenserFight monorepo — without merging. -author: '@lenserfight' -visibility: public -forkable: true -role: implementer -capabilities: - [ - code_review, - test_planning, - git_operations, - pr_creation, - root_cause_analysis, - migration_awareness, - ] -rays: [developer, github, productivity] -version: 0.1.0 --- # LenserFighter diff --git a/.lenserfight/lensers/startup-operator/LENSER.MD b/.lenserfight/lensers/startup-operator/SKILL.md similarity index 77% rename from .lenserfight/lensers/startup-operator/LENSER.MD rename to .lenserfight/lensers/startup-operator/SKILL.md index 099171db7..d00ad1381 100644 --- a/.lenserfight/lensers/startup-operator/LENSER.MD +++ b/.lenserfight/lensers/startup-operator/SKILL.md @@ -1,14 +1,6 @@ --- name: startup-operator -title: Startup Operator description: Founder/operator lenser for weekly reviews, roadmaps, GTM plans, launches, hiring loops, and customer learning. -author: '@lenserfight' -visibility: public -forkable: true -role: operator -capabilities: [roadmap_planning, gtm, launch_ops, hiring, customer_research] -rays: [startup, business, productivity] -version: 0.1.0 --- # Startup Operator diff --git a/.lenserfight/lenses/ai-cost-manager-reducer/LENS.MD b/.lenserfight/lenses/ai-cost-manager-reducer/SKILL.md similarity index 92% rename from .lenserfight/lenses/ai-cost-manager-reducer/LENS.MD rename to .lenserfight/lenses/ai-cost-manager-reducer/SKILL.md index 261b08d63..d93b896d8 100644 --- a/.lenserfight/lenses/ai-cost-manager-reducer/LENS.MD +++ b/.lenserfight/lenses/ai-cost-manager-reducer/SKILL.md @@ -1,22 +1,6 @@ --- name: ai-cost-manager-reducer -title: AI Cost Manager & Reducer description: Audit AI-powered features, API calls, agent workflows, prompt chains, tool calls, embeddings, vector search, retries, caching, and model selection to detect token waste and inefficient patterns. Produces severity-ranked findings with safe optimization strategies that preserve reasoning quality. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: scope - tool: textarea - required: true - example: "libs/domains/execution/src/ — battle evaluation pipeline and agent orchestration" - - label: context - tool: textarea - required: false - example: "Monthly AI bill doubled after scaling to 5k battles/day. Suspect the evaluation loop." -outputs: - kind: review -rays: [developer, operations] --- # AI Cost Manager & Reducer diff --git a/.lenserfight/lenses/ai-image-prompt-builder/LENS.MD b/.lenserfight/lenses/ai-image-prompt-builder/SKILL.md similarity index 69% rename from .lenserfight/lenses/ai-image-prompt-builder/LENS.MD rename to .lenserfight/lenses/ai-image-prompt-builder/SKILL.md index ef409ff0d..9e75381a0 100644 --- a/.lenserfight/lenses/ai-image-prompt-builder/LENS.MD +++ b/.lenserfight/lenses/ai-image-prompt-builder/SKILL.md @@ -1,23 +1,6 @@ --- name: ai-image-prompt-builder -title: AI Image Prompt Builder description: Crafts three structured text-to-image prompts with composition, lighting, palette, and negative constraints. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: subject - tool: text - required: true - example: A coffee bar at 6am with steam rising from a fresh pour-over - - label: style - tool: text - required: true - example: Cinematic, golden hour, shot on 35mm film -outputs: - kind: image -rays: [image, creator, ai, template] -seed_uuid: 45000000-0001-0003-0001-000000000001 --- # AI Image Prompt Builder diff --git a/.lenserfight/lenses/ai-output-comparator/LENS.MD b/.lenserfight/lenses/ai-output-comparator/SKILL.md similarity index 63% rename from .lenserfight/lenses/ai-output-comparator/LENS.MD rename to .lenserfight/lenses/ai-output-comparator/SKILL.md index 0fcc93e95..b0b7fb745 100644 --- a/.lenserfight/lenses/ai-output-comparator/LENS.MD +++ b/.lenserfight/lenses/ai-output-comparator/SKILL.md @@ -1,29 +1,6 @@ --- name: ai-output-comparator -title: AI Output Comparator (Claude / OpenAI / Gemini) description: Compares multiple AI outputs on the same task with a four-axis rubric and a willing-to-lose verdict. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: task - tool: textarea - required: true - example: Summarise the attached customer interview transcript into five themes - - label: outputs - tool: textarea - required: true - example: | - ## Claude - <output text> - ## OpenAI - <output text> - ## Gemini - <output text> -outputs: - kind: table -rays: [ai, claude, openai, gemini, analysis, template] -seed_uuid: 45000000-0001-000a-0001-000000000001 --- # AI Output Comparator @@ -45,4 +22,4 @@ People comparing AI models default to "they all sound fine." This lens forces a ## Related lenses -- [`deep-thinking-decision-helper`](../deep-thinking-decision-helper/LENS.MD) — when comparing approaches, not outputs +- [`deep-thinking-decision-helper`](../deep-thinking-decision-helper/SKILL.md) — when comparing approaches, not outputs diff --git a/.lenserfight/lenses/api-contract-reviewer/LENS.MD b/.lenserfight/lenses/api-contract-reviewer/SKILL.md similarity index 64% rename from .lenserfight/lenses/api-contract-reviewer/LENS.MD rename to .lenserfight/lenses/api-contract-reviewer/SKILL.md index 55a663b0a..40c266159 100644 --- a/.lenserfight/lenses/api-contract-reviewer/LENS.MD +++ b/.lenserfight/lenses/api-contract-reviewer/SKILL.md @@ -1,17 +1,6 @@ --- name: api-contract-reviewer -title: API Contract Reviewer description: Review request, response, DTO, and versioning changes for compatibility and consumer risk. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: contract_change - tool: textarea - required: true -outputs: - kind: review -rays: [developer, api, architecture] --- # API Contract Reviewer diff --git a/.lenserfight/lenses/architecture-decision-review/LENS.MD b/.lenserfight/lenses/architecture-decision-review/SKILL.md similarity index 60% rename from .lenserfight/lenses/architecture-decision-review/LENS.MD rename to .lenserfight/lenses/architecture-decision-review/SKILL.md index 0b60b9d4b..8876143f4 100644 --- a/.lenserfight/lenses/architecture-decision-review/LENS.MD +++ b/.lenserfight/lenses/architecture-decision-review/SKILL.md @@ -1,17 +1,6 @@ --- name: architecture-decision-review -title: Architecture Decision Review description: Review an architecture decision for constraints, trade-offs, coupling, and migration cost. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: decision - tool: textarea - required: true -outputs: - kind: memo -rays: [developer, architecture, startup] --- # Architecture Decision Review diff --git a/.lenserfight/lenses/async-standup-generator/LENS.MD b/.lenserfight/lenses/async-standup-generator/SKILL.md similarity index 72% rename from .lenserfight/lenses/async-standup-generator/LENS.MD rename to .lenserfight/lenses/async-standup-generator/SKILL.md index 2072f9066..f759850dc 100644 --- a/.lenserfight/lenses/async-standup-generator/LENS.MD +++ b/.lenserfight/lenses/async-standup-generator/SKILL.md @@ -1,21 +1,6 @@ --- name: async-standup-generator -title: Async Standup Generator description: Turns yesterday/today notes into a tight async standup with explicit blockers, risk flags, and one invite question. -author: '@chainabit' -visibility: public -forkable: true -inputs: - - label: yesterday - tool: textarea - required: true - - label: today - tool: textarea - required: true -outputs: - kind: text -rays: [chainabit, productivity, operator, text, template] -seed_uuid: 46000000-0001-0002-0001-000000000001 --- # Async Standup Generator diff --git a/.lenserfight/lenses/blog-outline-generator/LENS.MD b/.lenserfight/lenses/blog-outline-generator/SKILL.md similarity index 62% rename from .lenserfight/lenses/blog-outline-generator/LENS.MD rename to .lenserfight/lenses/blog-outline-generator/SKILL.md index 8312cbc9f..ded85cde1 100644 --- a/.lenserfight/lenses/blog-outline-generator/LENS.MD +++ b/.lenserfight/lenses/blog-outline-generator/SKILL.md @@ -1,23 +1,6 @@ --- name: blog-outline-generator -title: Blog Outline Generator description: Produces a complete blog outline with titles, meta description, H2/H3 structure, and SEO-aware angles. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: topic - tool: text - required: true - example: How to budget AI evaluations without overspending - - label: editorial_angle - tool: text - required: true - example: Contrarian — most teams over-test the wrong things -outputs: - kind: text -rays: [blog, content, creator, text, template] -seed_uuid: 45000000-0001-0002-0001-000000000001 --- # Blog Outline Generator @@ -41,5 +24,5 @@ Blog outlines from generic AI tools tend to be vague (`Introduction / Body / Con ## Related lenses -- [`youtube-script-generator`](../youtube-script-generator/LENS.MD) — same topic, different medium -- [`ai-image-prompt-builder`](../ai-image-prompt-builder/LENS.MD) — hero image prompts +- [`youtube-script-generator`](../youtube-script-generator/SKILL.md) — same topic, different medium +- [`ai-image-prompt-builder`](../ai-image-prompt-builder/SKILL.md) — hero image prompts diff --git a/.lenserfight/lenses/budget-planner/LENS.MD b/.lenserfight/lenses/budget-planner/SKILL.md similarity index 60% rename from .lenserfight/lenses/budget-planner/LENS.MD rename to .lenserfight/lenses/budget-planner/SKILL.md index 152891669..ee41ba8d8 100644 --- a/.lenserfight/lenses/budget-planner/LENS.MD +++ b/.lenserfight/lenses/budget-planner/SKILL.md @@ -1,17 +1,6 @@ --- name: budget-planner -title: Budget Planner description: Convert spending goals and constraints into a practical budget plan. This is not financial advice. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: budget_context - tool: textarea - required: true -outputs: - kind: table -rays: [finance, business, productivity] --- # Budget Planner diff --git a/.lenserfight/lenses/code-reviewer/LENS.MD b/.lenserfight/lenses/code-reviewer/SKILL.md similarity index 61% rename from .lenserfight/lenses/code-reviewer/LENS.MD rename to .lenserfight/lenses/code-reviewer/SKILL.md index f06264bd2..0cbf6dd5a 100644 --- a/.lenserfight/lenses/code-reviewer/LENS.MD +++ b/.lenserfight/lenses/code-reviewer/SKILL.md @@ -1,20 +1,6 @@ --- name: code-reviewer -title: Code Reviewer description: Review a diff for correctness, security, tests, maintainability, and release risk. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: diff - tool: textarea - required: true - - label: context - tool: textarea - required: false -outputs: - kind: review -rays: [developer, github, analysis] --- # Code Reviewer diff --git a/.lenserfight/lenses/competitive-analysis/LENS.MD b/.lenserfight/lenses/competitive-analysis/SKILL.md similarity index 58% rename from .lenserfight/lenses/competitive-analysis/LENS.MD rename to .lenserfight/lenses/competitive-analysis/SKILL.md index 27b1eabd9..287d870d3 100644 --- a/.lenserfight/lenses/competitive-analysis/LENS.MD +++ b/.lenserfight/lenses/competitive-analysis/SKILL.md @@ -1,17 +1,6 @@ --- name: competitive-analysis -title: Competitive Analysis description: Compare competitors by positioning, feature coverage, pricing, channel, and strategic risk. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: competitors - tool: textarea - required: true -outputs: - kind: table -rays: [startup, business, research] --- # Competitive Analysis diff --git a/.lenserfight/lenses/contract-summary/LENS.MD b/.lenserfight/lenses/contract-summary/SKILL.md similarity index 67% rename from .lenserfight/lenses/contract-summary/LENS.MD rename to .lenserfight/lenses/contract-summary/SKILL.md index a7775475c..ac7428ad5 100644 --- a/.lenserfight/lenses/contract-summary/LENS.MD +++ b/.lenserfight/lenses/contract-summary/SKILL.md @@ -1,17 +1,6 @@ --- name: contract-summary -title: Contract Summary description: Summarize a contract into obligations, deadlines, unusual terms, and lawyer questions. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: contract_text - tool: textarea - required: true -outputs: - kind: summary -rays: [legal, productivity] --- # Contract Summary diff --git a/.lenserfight/lenses/customer-interview-analysis/LENS.MD b/.lenserfight/lenses/customer-interview-analysis/SKILL.md similarity index 57% rename from .lenserfight/lenses/customer-interview-analysis/LENS.MD rename to .lenserfight/lenses/customer-interview-analysis/SKILL.md index 114fc2baa..3c482679a 100644 --- a/.lenserfight/lenses/customer-interview-analysis/LENS.MD +++ b/.lenserfight/lenses/customer-interview-analysis/SKILL.md @@ -1,17 +1,6 @@ --- name: customer-interview-analysis -title: Customer Interview Analysis description: Extract themes, pain, jobs-to-be-done, objections, and product implications from interviews. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: interview_notes - tool: textarea - required: true -outputs: - kind: analysis -rays: [startup, business, research] --- # Customer Interview Analysis diff --git a/.lenserfight/lenses/daily-productivity-planner/LENS.MD b/.lenserfight/lenses/daily-productivity-planner/SKILL.md similarity index 63% rename from .lenserfight/lenses/daily-productivity-planner/LENS.MD rename to .lenserfight/lenses/daily-productivity-planner/SKILL.md index 841004a04..467130211 100644 --- a/.lenserfight/lenses/daily-productivity-planner/LENS.MD +++ b/.lenserfight/lenses/daily-productivity-planner/SKILL.md @@ -1,29 +1,6 @@ --- name: daily-productivity-planner -title: Daily Productivity Planner description: Picks the highest-leverage outcome of the day, time-blocks around existing commitments, and surfaces a "won't do" list. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: open_goals - tool: textarea - required: true - example: | - - Finish RLS migration review - - Ship onboarding copy v2 - - Draft Q4 roadmap doc - - label: calendar - tool: textarea - required: true - example: | - 09:30-10:00 — 1:1 with Mert - 13:00-14:30 — Design crit - 16:00-17:00 — Customer call -outputs: - kind: checklist -rays: [productivity, planning, checklist, template] -seed_uuid: 45000000-0001-0009-0001-000000000001 --- # Daily Productivity Planner diff --git a/.lenserfight/lenses/decision-memo/LENS.MD b/.lenserfight/lenses/decision-memo/SKILL.md similarity index 58% rename from .lenserfight/lenses/decision-memo/LENS.MD rename to .lenserfight/lenses/decision-memo/SKILL.md index eeb27ed69..3a399cfc2 100644 --- a/.lenserfight/lenses/decision-memo/LENS.MD +++ b/.lenserfight/lenses/decision-memo/SKILL.md @@ -1,17 +1,6 @@ --- name: decision-memo -title: Decision Memo description: Convert a choice into an explicit decision memo with options, trade-offs, and next actions. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: decision_context - tool: textarea - required: true -outputs: - kind: memo -rays: [productivity, startup, business] --- # Decision Memo diff --git a/.lenserfight/lenses/deep-thinking-decision-helper/LENS.MD b/.lenserfight/lenses/deep-thinking-decision-helper/SKILL.md similarity index 70% rename from .lenserfight/lenses/deep-thinking-decision-helper/LENS.MD rename to .lenserfight/lenses/deep-thinking-decision-helper/SKILL.md index ec739cbed..0f1f116a8 100644 --- a/.lenserfight/lenses/deep-thinking-decision-helper/LENS.MD +++ b/.lenserfight/lenses/deep-thinking-decision-helper/SKILL.md @@ -1,23 +1,6 @@ --- name: deep-thinking-decision-helper -title: Deep Thinking Decision Helper description: Reframes a decision, surfaces assumptions and second-order effects, and recommends a decision criterion. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: decision - tool: textarea - required: true - example: Should we hire a second backend engineer this quarter or wait until Q1? - - label: constraints - tool: textarea - required: true - example: Runway 12 months, current hire ramping, no senior bench -outputs: - kind: text -rays: [deep-thinking, planning, analysis, template] -seed_uuid: 45000000-0001-0008-0001-000000000001 --- # Deep Thinking Decision Helper diff --git a/.lenserfight/lenses/diagram-explainer/LENS.MD b/.lenserfight/lenses/diagram-explainer/SKILL.md similarity index 55% rename from .lenserfight/lenses/diagram-explainer/LENS.MD rename to .lenserfight/lenses/diagram-explainer/SKILL.md index 2aeea99a2..a584df091 100644 --- a/.lenserfight/lenses/diagram-explainer/LENS.MD +++ b/.lenserfight/lenses/diagram-explainer/SKILL.md @@ -1,17 +1,6 @@ --- name: diagram-explainer -title: Diagram Explainer description: Explain a diagram, architecture sketch, or flowchart in plain language. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: diagram_notes - tool: textarea - required: true -outputs: - kind: explanation -rays: [developer, multimodal, analysis] --- # Diagram Explainer diff --git a/.lenserfight/lenses/excel-formula-assistant/LENS.MD b/.lenserfight/lenses/excel-formula-assistant/SKILL.md similarity index 67% rename from .lenserfight/lenses/excel-formula-assistant/LENS.MD rename to .lenserfight/lenses/excel-formula-assistant/SKILL.md index c303475a5..fb0e22138 100644 --- a/.lenserfight/lenses/excel-formula-assistant/LENS.MD +++ b/.lenserfight/lenses/excel-formula-assistant/SKILL.md @@ -1,23 +1,6 @@ --- name: excel-formula-assistant -title: Excel Formula Assistant description: Builds Excel-365 and Google Sheets formulas with pitfalls, validation, and plain-English explanation. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: goal - tool: textarea - required: true - example: For every row, return the most-recent invoice date for that customer - - label: columns - tool: textarea - required: true - example: 'A: customer_id, B: invoice_id, C: invoice_date, D: amount; first 5 sample rows below…' -outputs: - kind: text -rays: [excel, productivity, analysis, template] -seed_uuid: 45000000-0001-0005-0001-000000000001 --- # Excel Formula Assistant diff --git a/.lenserfight/lenses/finance-report-explainer/LENS.MD b/.lenserfight/lenses/finance-report-explainer/SKILL.md similarity index 65% rename from .lenserfight/lenses/finance-report-explainer/LENS.MD rename to .lenserfight/lenses/finance-report-explainer/SKILL.md index 70f9bfba7..4556cf91e 100644 --- a/.lenserfight/lenses/finance-report-explainer/LENS.MD +++ b/.lenserfight/lenses/finance-report-explainer/SKILL.md @@ -1,28 +1,6 @@ --- name: finance-report-explainer -title: Finance Report Explainer description: Plain-language explanation of a finance report with audience-aware framing. Analysis only — not certified advice. -author: '@lenserfight' -visibility: public -forkable: true -disclaimer: | - This explanation is an analysis aid only and is NOT certified financial advice, - audit work, investment recommendation, or tax guidance. Verify all figures - against source records and consult a qualified professional before acting on - this material. -inputs: - - label: financial_data - tool: textarea - required: true - example: Q3 P&L summary with revenue, gross margin, opex, and cash position - - label: audience - tool: text - required: true - example: Non-finance board members -outputs: - kind: table -rays: [finance, analysis, table, template] -seed_uuid: 45000000-0001-0004-0001-000000000001 --- # Finance Report Explainer diff --git a/.lenserfight/lenses/founder-weekly-review/LENS.MD b/.lenserfight/lenses/founder-weekly-review/SKILL.md similarity index 59% rename from .lenserfight/lenses/founder-weekly-review/LENS.MD rename to .lenserfight/lenses/founder-weekly-review/SKILL.md index 619889651..d3ffce199 100644 --- a/.lenserfight/lenses/founder-weekly-review/LENS.MD +++ b/.lenserfight/lenses/founder-weekly-review/SKILL.md @@ -1,17 +1,6 @@ --- name: founder-weekly-review -title: Founder Weekly Review description: Turn weekly startup notes into decisions, risks, blockers, and next-week operating plan. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: weekly_notes - tool: textarea - required: true -outputs: - kind: memo -rays: [startup, productivity] --- # Founder Weekly Review diff --git a/.lenserfight/lenses/github-issue-solver/LENS.MD b/.lenserfight/lenses/github-issue-solver/SKILL.md similarity index 78% rename from .lenserfight/lenses/github-issue-solver/LENS.MD rename to .lenserfight/lenses/github-issue-solver/SKILL.md index 826b3536f..3f9859236 100644 --- a/.lenserfight/lenses/github-issue-solver/LENS.MD +++ b/.lenserfight/lenses/github-issue-solver/SKILL.md @@ -1,26 +1,6 @@ --- name: github-issue-solver -title: GitHub Issue Solver description: Analyze a GitHub issue, identify root cause, design a GRASP-compliant fix, produce an implementation plan, and draft a PR description. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: issue - tool: textarea - required: true - example: "Issue #86: Text overflow in mobile PageHeader when username is long" - - label: codebase_context - tool: textarea - required: false - example: "Relevant file: apps/web/src/components/PageHeader.tsx. The component uses flex layout with no truncation." - - label: constraints - tool: textarea - required: false - example: "Cannot change PageHeader API. Must work on iOS Safari." -outputs: - kind: text -rays: [developer, github, productivity] --- # GitHub Issue Solver diff --git a/.lenserfight/lenses/github-issue-triage/LENS.MD b/.lenserfight/lenses/github-issue-triage/SKILL.md similarity index 62% rename from .lenserfight/lenses/github-issue-triage/LENS.MD rename to .lenserfight/lenses/github-issue-triage/SKILL.md index 1586b9a37..c6352db22 100644 --- a/.lenserfight/lenses/github-issue-triage/LENS.MD +++ b/.lenserfight/lenses/github-issue-triage/SKILL.md @@ -1,17 +1,6 @@ --- name: github-issue-triage -title: GitHub Issue Triage description: Triage issues into bug, feature, support, duplicate, or needs-info with labels and next action. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: issue - tool: textarea - required: true -outputs: - kind: table -rays: [developer, github, productivity] --- # GitHub Issue Triage diff --git a/.lenserfight/lenses/go-to-market-planner/LENS.MD b/.lenserfight/lenses/go-to-market-planner/SKILL.md similarity index 59% rename from .lenserfight/lenses/go-to-market-planner/LENS.MD rename to .lenserfight/lenses/go-to-market-planner/SKILL.md index a50d04b0c..426ff46ec 100644 --- a/.lenserfight/lenses/go-to-market-planner/LENS.MD +++ b/.lenserfight/lenses/go-to-market-planner/SKILL.md @@ -1,17 +1,6 @@ --- name: go-to-market-planner -title: Go To Market Planner description: Build a GTM plan from product, audience, positioning, channels, and launch constraints. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: gtm_context - tool: textarea - required: true -outputs: - kind: plan -rays: [startup, business] --- # Go To Market Planner diff --git a/.lenserfight/lenses/hiring-loop-designer/LENS.MD b/.lenserfight/lenses/hiring-loop-designer/SKILL.md similarity index 68% rename from .lenserfight/lenses/hiring-loop-designer/LENS.MD rename to .lenserfight/lenses/hiring-loop-designer/SKILL.md index 09d339031..c70fa0761 100644 --- a/.lenserfight/lenses/hiring-loop-designer/LENS.MD +++ b/.lenserfight/lenses/hiring-loop-designer/SKILL.md @@ -1,23 +1,6 @@ --- name: hiring-loop-designer -title: Hiring Loop Designer description: Signal-first 4-stage interview loop with anti-loop, candidate one-pager, and the failure mode the loop is exposed to. -author: '@chainabit' -visibility: public -forkable: true -inputs: - - label: role_profile - tool: textarea - required: true - example: Senior product engineer, full-stack, comfortable owning a feature end-to-end - - label: constraints - tool: textarea - required: true - example: Budget cap $180k OTE, manager has 4h/week of interview bandwidth, urgency 4 weeks -outputs: - kind: checklist -rays: [chainabit, operator, planning, checklist, template] -seed_uuid: 46000000-0001-0005-0001-000000000001 --- # Hiring Loop Designer diff --git a/.lenserfight/lenses/incident-postmortem/LENS.MD b/.lenserfight/lenses/incident-postmortem/SKILL.md similarity index 60% rename from .lenserfight/lenses/incident-postmortem/LENS.MD rename to .lenserfight/lenses/incident-postmortem/SKILL.md index e28040be1..5b3cd2fa9 100644 --- a/.lenserfight/lenses/incident-postmortem/LENS.MD +++ b/.lenserfight/lenses/incident-postmortem/SKILL.md @@ -1,17 +1,6 @@ --- name: incident-postmortem -title: Incident Postmortem description: Produce a blameless incident review with timeline, impact, root causes, and action items. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: incident_notes - tool: textarea - required: true -outputs: - kind: report -rays: [developer, operations, business] --- # Incident Postmortem diff --git a/.lenserfight/lenses/intent-clarifier/LENS.MD b/.lenserfight/lenses/intent-clarifier/SKILL.md similarity index 56% rename from .lenserfight/lenses/intent-clarifier/LENS.MD rename to .lenserfight/lenses/intent-clarifier/SKILL.md index 605f71909..6b3e377fc 100644 --- a/.lenserfight/lenses/intent-clarifier/LENS.MD +++ b/.lenserfight/lenses/intent-clarifier/SKILL.md @@ -1,17 +1,6 @@ --- name: intent-clarifier -title: Intent Clarifier description: Clarify audience, goal, assumptions, constraints, and success criteria before drafting. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: brief - tool: textarea - required: true -outputs: - kind: brief -rays: [creator, productivity, analysis] --- # Intent Clarifier diff --git a/.lenserfight/lenses/investor-update-drafter/LENS.MD b/.lenserfight/lenses/investor-update-drafter/SKILL.md similarity index 61% rename from .lenserfight/lenses/investor-update-drafter/LENS.MD rename to .lenserfight/lenses/investor-update-drafter/SKILL.md index 5b1752d02..cded38f81 100644 --- a/.lenserfight/lenses/investor-update-drafter/LENS.MD +++ b/.lenserfight/lenses/investor-update-drafter/SKILL.md @@ -1,17 +1,6 @@ --- name: investor-update-drafter -title: Investor Update Drafter description: Draft a crisp investor update with metrics, wins, asks, risks, and next milestones. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: update_notes - tool: textarea - required: true -outputs: - kind: memo -rays: [startup, finance, business] --- # Investor Update Drafter diff --git a/.lenserfight/lenses/kpi-reviewer/LENS.MD b/.lenserfight/lenses/kpi-reviewer/SKILL.md similarity index 59% rename from .lenserfight/lenses/kpi-reviewer/LENS.MD rename to .lenserfight/lenses/kpi-reviewer/SKILL.md index d194d8c32..cad04616c 100644 --- a/.lenserfight/lenses/kpi-reviewer/LENS.MD +++ b/.lenserfight/lenses/kpi-reviewer/SKILL.md @@ -1,17 +1,6 @@ --- name: kpi-reviewer -title: KPI Reviewer description: Review KPIs for trend, quality, causality, and operating decisions. This is not financial advice. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: kpis - tool: textarea - required: true -outputs: - kind: table -rays: [finance, business, startup] --- # KPI Reviewer diff --git a/.lenserfight/lenses/launch-checklist/LENS.MD b/.lenserfight/lenses/launch-checklist/SKILL.md similarity index 57% rename from .lenserfight/lenses/launch-checklist/LENS.MD rename to .lenserfight/lenses/launch-checklist/SKILL.md index 9ca3b773c..767c614ca 100644 --- a/.lenserfight/lenses/launch-checklist/LENS.MD +++ b/.lenserfight/lenses/launch-checklist/SKILL.md @@ -1,17 +1,6 @@ --- name: launch-checklist -title: Launch Checklist description: Build a launch checklist across product, marketing, support, analytics, risk, and rollback. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: launch_context - tool: textarea - required: true -outputs: - kind: checklist -rays: [startup, business, operations] --- # Launch Checklist diff --git a/.lenserfight/lenses/launch-content-kit/LENS.MD b/.lenserfight/lenses/launch-content-kit/SKILL.md similarity index 70% rename from .lenserfight/lenses/launch-content-kit/LENS.MD rename to .lenserfight/lenses/launch-content-kit/SKILL.md index e41585a62..6088ed0eb 100644 --- a/.lenserfight/lenses/launch-content-kit/LENS.MD +++ b/.lenserfight/lenses/launch-content-kit/SKILL.md @@ -1,23 +1,6 @@ --- name: launch-content-kit -title: Launch Content Kit description: Launch-week content — tweet+thread, LinkedIn post, email teaser, community opener, and an anti-pattern callout. -author: '@chainabit' -visibility: public -forkable: true -inputs: - - label: launch_subject - tool: textarea - required: true - example: Public beta of LenserFight battle templates - - label: channels - tool: text - required: true - example: Twitter, LinkedIn, weekly email, Show HN -outputs: - kind: text -rays: [chainabit, marketing, content, text, template] -seed_uuid: 46000000-0001-0004-0001-000000000001 --- # Launch Content Kit diff --git a/.lenserfight/lenses/legal-contract-reviewer/LENS.MD b/.lenserfight/lenses/legal-contract-reviewer/SKILL.md similarity index 71% rename from .lenserfight/lenses/legal-contract-reviewer/LENS.MD rename to .lenserfight/lenses/legal-contract-reviewer/SKILL.md index 062783cb2..66f9cdbff 100644 --- a/.lenserfight/lenses/legal-contract-reviewer/LENS.MD +++ b/.lenserfight/lenses/legal-contract-reviewer/SKILL.md @@ -1,28 +1,6 @@ --- name: legal-contract-reviewer -title: Legal Contract Reviewer description: Plain-language contract summary, clause-risk table, and questions to ask a lawyer. Analysis only — NOT legal advice. -author: '@lenserfight' -visibility: public -forkable: true -disclaimer: | - This review is an analysis aid only and is NOT legal advice. It does not - establish an attorney-client relationship. Always have a qualified, licensed - lawyer in your jurisdiction review the actual document before signing, - negotiating, or relying on it. -inputs: - - label: contract_text - tool: textarea - required: true - example: Mutual NDA between two early-stage startups, two pages - - label: your_role - tool: text - required: true - example: Receiving party (the smaller startup) -outputs: - kind: table -rays: [legal, analysis, table, template] -seed_uuid: 45000000-0001-0006-0001-000000000001 --- # Legal Contract Reviewer diff --git a/.lenserfight/lenses/legal-risk-checklist/LENS.MD b/.lenserfight/lenses/legal-risk-checklist/SKILL.md similarity index 63% rename from .lenserfight/lenses/legal-risk-checklist/LENS.MD rename to .lenserfight/lenses/legal-risk-checklist/SKILL.md index cefd77f9a..3d725f137 100644 --- a/.lenserfight/lenses/legal-risk-checklist/LENS.MD +++ b/.lenserfight/lenses/legal-risk-checklist/SKILL.md @@ -1,17 +1,6 @@ --- name: legal-risk-checklist -title: Legal Risk Checklist description: Create a legal-adjacent review checklist. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: document_context - tool: textarea - required: true -outputs: - kind: checklist -rays: [legal, productivity] --- # Legal Risk Checklist diff --git a/.lenserfight/lenses/meeting-notes-summarizer/LENS.MD b/.lenserfight/lenses/meeting-notes-summarizer/SKILL.md similarity index 58% rename from .lenserfight/lenses/meeting-notes-summarizer/LENS.MD rename to .lenserfight/lenses/meeting-notes-summarizer/SKILL.md index 1b539cd2b..ad67cb6a6 100644 --- a/.lenserfight/lenses/meeting-notes-summarizer/LENS.MD +++ b/.lenserfight/lenses/meeting-notes-summarizer/SKILL.md @@ -1,17 +1,6 @@ --- name: meeting-notes-summarizer -title: Meeting Notes Summarizer description: Turn messy meeting notes into decisions, action items, risks, and unresolved questions. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: meeting_notes - tool: textarea - required: true -outputs: - kind: memo -rays: [productivity, business] --- # Meeting Notes Summarizer diff --git a/.lenserfight/lenses/newsletter-writer/LENS.MD b/.lenserfight/lenses/newsletter-writer/SKILL.md similarity index 57% rename from .lenserfight/lenses/newsletter-writer/LENS.MD rename to .lenserfight/lenses/newsletter-writer/SKILL.md index e61029323..823700678 100644 --- a/.lenserfight/lenses/newsletter-writer/LENS.MD +++ b/.lenserfight/lenses/newsletter-writer/SKILL.md @@ -1,17 +1,6 @@ --- name: newsletter-writer -title: Newsletter Writer description: Draft a concise newsletter issue from notes, links, or product updates. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: notes - tool: textarea - required: true -outputs: - kind: text -rays: [creator, blog, business] --- # Newsletter Writer diff --git a/.lenserfight/lenses/policy-comparison/LENS.MD b/.lenserfight/lenses/policy-comparison/SKILL.md similarity index 65% rename from .lenserfight/lenses/policy-comparison/LENS.MD rename to .lenserfight/lenses/policy-comparison/SKILL.md index 493b42146..59decae3a 100644 --- a/.lenserfight/lenses/policy-comparison/LENS.MD +++ b/.lenserfight/lenses/policy-comparison/SKILL.md @@ -1,17 +1,6 @@ --- name: policy-comparison -title: Policy Comparison description: Compare two policies and surface practical differences. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: policies - tool: textarea - required: true -outputs: - kind: table -rays: [legal, business] --- # Policy Comparison diff --git a/.lenserfight/lenses/pr-description-writer/LENS.MD b/.lenserfight/lenses/pr-description-writer/SKILL.md similarity index 58% rename from .lenserfight/lenses/pr-description-writer/LENS.MD rename to .lenserfight/lenses/pr-description-writer/SKILL.md index 854bd530d..8ef087b53 100644 --- a/.lenserfight/lenses/pr-description-writer/LENS.MD +++ b/.lenserfight/lenses/pr-description-writer/SKILL.md @@ -1,20 +1,6 @@ --- name: pr-description-writer -title: PR Description Writer description: Draft a reviewer-ready pull request description from a diff summary and validation notes. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: changes - tool: textarea - required: true - - label: validation - tool: textarea - required: false -outputs: - kind: text -rays: [developer, github] --- # PR Description Writer diff --git a/.lenserfight/lenses/pr-triage-brief/LENS.MD b/.lenserfight/lenses/pr-triage-brief/SKILL.md similarity index 67% rename from .lenserfight/lenses/pr-triage-brief/LENS.MD rename to .lenserfight/lenses/pr-triage-brief/SKILL.md index 97dd417ef..90ff920df 100644 --- a/.lenserfight/lenses/pr-triage-brief/LENS.MD +++ b/.lenserfight/lenses/pr-triage-brief/SKILL.md @@ -1,23 +1,6 @@ --- name: pr-triage-brief -title: PR Triage Brief description: Opinionated review-queue triage — prioritised table, split/rebase candidates, park-or-close drafts, and pattern risks. -author: '@chainabit' -visibility: public -forkable: true -inputs: - - label: open_prs - tool: textarea - required: true - example: List of PR numbers with title and author - - label: eng_goals - tool: textarea - required: true - example: This week we are shipping the new RLS policy and the discovery feed. -outputs: - kind: table -rays: [chainabit, github, developer, table, template] -seed_uuid: 46000000-0001-0003-0001-000000000001 --- # PR Triage Brief diff --git a/.lenserfight/lenses/questions-for-lawyer/LENS.MD b/.lenserfight/lenses/questions-for-lawyer/SKILL.md similarity index 66% rename from .lenserfight/lenses/questions-for-lawyer/LENS.MD rename to .lenserfight/lenses/questions-for-lawyer/SKILL.md index 66581fcf9..6f6f3284f 100644 --- a/.lenserfight/lenses/questions-for-lawyer/LENS.MD +++ b/.lenserfight/lenses/questions-for-lawyer/SKILL.md @@ -1,17 +1,6 @@ --- name: questions-for-lawyer -title: Questions For Lawyer description: Convert legal concerns into clear questions for qualified counsel. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: concerns - tool: textarea - required: true -outputs: - kind: list -rays: [legal, productivity] --- # Questions For Lawyer diff --git a/.lenserfight/lenses/react-native-performance-reviewer/LENS.MD b/.lenserfight/lenses/react-native-performance-reviewer/SKILL.md similarity index 91% rename from .lenserfight/lenses/react-native-performance-reviewer/LENS.MD rename to .lenserfight/lenses/react-native-performance-reviewer/SKILL.md index 3ff5baecb..23b77b666 100644 --- a/.lenserfight/lenses/react-native-performance-reviewer/LENS.MD +++ b/.lenserfight/lenses/react-native-performance-reviewer/SKILL.md @@ -1,22 +1,6 @@ --- name: react-native-performance-reviewer -title: React Native / Expo Go Performance Reviewer description: Review React Native and Expo Go code for mobile performance, memory usage, CPU pressure, battery impact, network efficiency, and behavior under real-world stress. Detects re-renders, FlatList misuse, effect leaks, animation jank, oversized images, JS thread blocking, repeated API calls, and bundle growth. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: diff - tool: textarea - required: true - example: "apps/mobile/src/screens/FeedScreen.tsx — added infinite scroll with FlatList" - - label: context - tool: textarea - required: false - example: "Target: Android mid-range 2GB RAM. Users report scroll jank after 50 items." -outputs: - kind: review -rays: [developer] --- # React Native / Expo Go Performance Reviewer diff --git a/.lenserfight/lenses/react-vite-performance-reviewer/LENS.MD b/.lenserfight/lenses/react-vite-performance-reviewer/SKILL.md similarity index 92% rename from .lenserfight/lenses/react-vite-performance-reviewer/LENS.MD rename to .lenserfight/lenses/react-vite-performance-reviewer/SKILL.md index 572f9c9ac..56a749d67 100644 --- a/.lenserfight/lenses/react-vite-performance-reviewer/LENS.MD +++ b/.lenserfight/lenses/react-vite-performance-reviewer/SKILL.md @@ -1,22 +1,6 @@ --- name: react-vite-performance-reviewer -title: React / Vite Performance Reviewer description: Review React and Vite web app code for browser performance, memory usage, bundle size, rendering speed, network cost, and behavior under high traffic, slow devices, and large datasets. Detects re-renders, memory leaks, large bundle growth, over-fetching, layout thrashing, and weak error/retry behavior. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: diff - tool: textarea - required: true - example: "apps/web/src/features/battles/BattleList.tsx — added infinite scroll with 500+ rows" - - label: context - tool: textarea - required: false - example: "Users report slow LCP on the battles page. Bundle size increased by 40KB in last PR." -outputs: - kind: review -rays: [developer] --- # React / Vite Performance Reviewer diff --git a/.lenserfight/lenses/reasoning-quality-comparison/LENS.MD b/.lenserfight/lenses/reasoning-quality-comparison/SKILL.md similarity index 61% rename from .lenserfight/lenses/reasoning-quality-comparison/LENS.MD rename to .lenserfight/lenses/reasoning-quality-comparison/SKILL.md index b7acfe874..db16c1f72 100644 --- a/.lenserfight/lenses/reasoning-quality-comparison/LENS.MD +++ b/.lenserfight/lenses/reasoning-quality-comparison/SKILL.md @@ -1,17 +1,6 @@ --- name: reasoning-quality-comparison -title: Reasoning Quality Comparison description: Compare model outputs for evidence use, assumptions, edge cases, and decision usefulness. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: outputs - tool: textarea - required: true -outputs: - kind: scorecard -rays: [ai-comparison, openai, claude, gemini] --- # Reasoning Quality Comparison diff --git a/.lenserfight/lenses/refactor-planner/LENS.MD b/.lenserfight/lenses/refactor-planner/SKILL.md similarity index 59% rename from .lenserfight/lenses/refactor-planner/LENS.MD rename to .lenserfight/lenses/refactor-planner/SKILL.md index 00696be0f..45ad4a7e2 100644 --- a/.lenserfight/lenses/refactor-planner/LENS.MD +++ b/.lenserfight/lenses/refactor-planner/SKILL.md @@ -1,17 +1,6 @@ --- name: refactor-planner -title: Refactor Planner description: Turn a messy code area into a scoped refactor plan with risk controls. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: code_area - tool: textarea - required: true -outputs: - kind: plan -rays: [developer, architecture, productivity] --- # Refactor Planner diff --git a/.lenserfight/lenses/release-note-generator/LENS.MD b/.lenserfight/lenses/release-note-generator/SKILL.md similarity index 58% rename from .lenserfight/lenses/release-note-generator/LENS.MD rename to .lenserfight/lenses/release-note-generator/SKILL.md index 781b9c957..bceb45838 100644 --- a/.lenserfight/lenses/release-note-generator/LENS.MD +++ b/.lenserfight/lenses/release-note-generator/SKILL.md @@ -1,17 +1,6 @@ --- name: release-note-generator -title: Release Note Generator description: Convert merged changes into user-facing and operator-facing release notes. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: changes - tool: textarea - required: true -outputs: - kind: changelog -rays: [developer, operations, productivity] --- # Release Note Generator diff --git a/.lenserfight/lenses/revenue-experiment-planner/LENS.MD b/.lenserfight/lenses/revenue-experiment-planner/SKILL.md similarity index 61% rename from .lenserfight/lenses/revenue-experiment-planner/LENS.MD rename to .lenserfight/lenses/revenue-experiment-planner/SKILL.md index 6eba7acf8..ba55004f6 100644 --- a/.lenserfight/lenses/revenue-experiment-planner/LENS.MD +++ b/.lenserfight/lenses/revenue-experiment-planner/SKILL.md @@ -1,17 +1,6 @@ --- name: revenue-experiment-planner -title: Revenue Experiment Planner description: Plan a revenue experiment with hypothesis, segment, offer, success metric, and guardrails. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: experiment_context - tool: textarea - required: true -outputs: - kind: plan -rays: [startup, finance, business] --- # Revenue Experiment Planner diff --git a/.lenserfight/lenses/screenshot-review/LENS.MD b/.lenserfight/lenses/screenshot-review/SKILL.md similarity index 57% rename from .lenserfight/lenses/screenshot-review/LENS.MD rename to .lenserfight/lenses/screenshot-review/SKILL.md index 62b9c08d2..24e0f3068 100644 --- a/.lenserfight/lenses/screenshot-review/LENS.MD +++ b/.lenserfight/lenses/screenshot-review/SKILL.md @@ -1,17 +1,6 @@ --- name: screenshot-review -title: Screenshot Review description: Review a screenshot for UX clarity, accessibility risk, layout problems, and copy issues. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: screenshot_notes - tool: textarea - required: true -outputs: - kind: review -rays: [developer, creator, multimodal] --- # Screenshot Review diff --git a/.lenserfight/lenses/short-form-video-repurposer/LENS.MD b/.lenserfight/lenses/short-form-video-repurposer/SKILL.md similarity index 56% rename from .lenserfight/lenses/short-form-video-repurposer/LENS.MD rename to .lenserfight/lenses/short-form-video-repurposer/SKILL.md index 8c89c5cb3..141931780 100644 --- a/.lenserfight/lenses/short-form-video-repurposer/LENS.MD +++ b/.lenserfight/lenses/short-form-video-repurposer/SKILL.md @@ -1,17 +1,6 @@ --- name: short-form-video-repurposer -title: Short-Form Video Repurposer description: Convert long-form content into short vertical video concepts with hooks and captions. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: source_content - tool: textarea - required: true -outputs: - kind: list -rays: [creator, youtube, social, multimodal] --- # Short-Form Video Repurposer diff --git a/.lenserfight/lenses/smart-commit/LENS.MD b/.lenserfight/lenses/smart-commit/SKILL.md similarity index 92% rename from .lenserfight/lenses/smart-commit/LENS.MD rename to .lenserfight/lenses/smart-commit/SKILL.md index 0d66c9a46..c0ff2d7a7 100644 --- a/.lenserfight/lenses/smart-commit/LENS.MD +++ b/.lenserfight/lenses/smart-commit/SKILL.md @@ -1,18 +1,6 @@ --- name: smart-commit -title: Smart Commit description: Inspect the working tree, classify every change by conventional-commit type, group into logical commit units, and commit each group separately with explicit user approval. Never merges unrelated changes into one commit. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: instructions - tool: textarea - required: false - example: "Keep DB migration in its own commit. Skip lockfile changes." -outputs: - kind: text -rays: [developer, productivity] --- # Smart Commit diff --git a/.lenserfight/lenses/social-post-generator/LENS.MD b/.lenserfight/lenses/social-post-generator/SKILL.md similarity index 57% rename from .lenserfight/lenses/social-post-generator/LENS.MD rename to .lenserfight/lenses/social-post-generator/SKILL.md index 988455ec6..eed041cfe 100644 --- a/.lenserfight/lenses/social-post-generator/LENS.MD +++ b/.lenserfight/lenses/social-post-generator/SKILL.md @@ -1,17 +1,6 @@ --- name: social-post-generator -title: Social Post Generator description: Convert an announcement or article into platform-specific social posts. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: source - tool: textarea - required: true -outputs: - kind: text -rays: [creator, social, business] --- # Social Post Generator diff --git a/.lenserfight/lenses/startup-roadmap-designer/LENS.MD b/.lenserfight/lenses/startup-roadmap-designer/SKILL.md similarity index 62% rename from .lenserfight/lenses/startup-roadmap-designer/LENS.MD rename to .lenserfight/lenses/startup-roadmap-designer/SKILL.md index 9200f1020..a050c0544 100644 --- a/.lenserfight/lenses/startup-roadmap-designer/LENS.MD +++ b/.lenserfight/lenses/startup-roadmap-designer/SKILL.md @@ -1,23 +1,6 @@ --- name: startup-roadmap-designer -title: Startup Roadmap Designer description: Builds a 12-week startup roadmap with metrics, milestones, risks, and kill criteria — calibrated to current stage. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: idea - tool: textarea - required: true - example: A team-wide AI evaluation harness for early-stage product teams - - label: current_stage - tool: text - required: true - example: 'Pre-product, two founders, three customer interviews' -outputs: - kind: table -rays: [startup, planning, table, template] -seed_uuid: 45000000-0001-0007-0001-000000000001 --- # Startup Roadmap Designer @@ -40,5 +23,5 @@ Roadmap generators produce calendar-flavoured wishlists. This lens forces a kill ## Related lenses -- [`deep-thinking-decision-helper`](../deep-thinking-decision-helper/LENS.MD) — for individual decisions inside the roadmap -- [`weekly-operating-review`](../weekly-operating-review/LENS.MD) — for ongoing operations after the roadmap is committed +- [`deep-thinking-decision-helper`](../deep-thinking-decision-helper/SKILL.md) — for individual decisions inside the roadmap +- [`weekly-operating-review`](../weekly-operating-review/SKILL.md) — for ongoing operations after the roadmap is committed diff --git a/.lenserfight/lenses/task-prioritization/LENS.MD b/.lenserfight/lenses/task-prioritization/SKILL.md similarity index 53% rename from .lenserfight/lenses/task-prioritization/LENS.MD rename to .lenserfight/lenses/task-prioritization/SKILL.md index f1cab942a..a98e5c264 100644 --- a/.lenserfight/lenses/task-prioritization/LENS.MD +++ b/.lenserfight/lenses/task-prioritization/SKILL.md @@ -1,17 +1,6 @@ --- name: task-prioritization -title: Task Prioritization description: Rank tasks by impact, urgency, dependency, effort, and risk. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: task_list - tool: textarea - required: true -outputs: - kind: table -rays: [productivity, business] --- # Task Prioritization diff --git a/.lenserfight/lenses/terms-of-service-review/LENS.MD b/.lenserfight/lenses/terms-of-service-review/SKILL.md similarity index 66% rename from .lenserfight/lenses/terms-of-service-review/LENS.MD rename to .lenserfight/lenses/terms-of-service-review/SKILL.md index 0bb21394d..20969ef90 100644 --- a/.lenserfight/lenses/terms-of-service-review/LENS.MD +++ b/.lenserfight/lenses/terms-of-service-review/SKILL.md @@ -1,17 +1,6 @@ --- name: terms-of-service-review -title: Terms Of Service Review description: Review terms of service for practical user or business risks. This is not legal advice and must be reviewed by a qualified lawyer. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: terms_text - tool: textarea - required: true -outputs: - kind: table -rays: [legal, business] --- # Terms Of Service Review diff --git a/.lenserfight/lenses/thumbnail-prompt-generator/LENS.MD b/.lenserfight/lenses/thumbnail-prompt-generator/SKILL.md similarity index 58% rename from .lenserfight/lenses/thumbnail-prompt-generator/LENS.MD rename to .lenserfight/lenses/thumbnail-prompt-generator/SKILL.md index 2cd4b0cca..70c64b22a 100644 --- a/.lenserfight/lenses/thumbnail-prompt-generator/LENS.MD +++ b/.lenserfight/lenses/thumbnail-prompt-generator/SKILL.md @@ -1,17 +1,6 @@ --- name: thumbnail-prompt-generator -title: Thumbnail Prompt Generator description: Generate image prompts and layout notes for clear, clickable video thumbnails. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: video_topic - tool: textarea - required: true -outputs: - kind: image_prompt -rays: [creator, youtube, multimodal] --- # Thumbnail Prompt Generator diff --git a/.lenserfight/lenses/unit-test-generator/LENS.MD b/.lenserfight/lenses/unit-test-generator/SKILL.md similarity index 65% rename from .lenserfight/lenses/unit-test-generator/LENS.MD rename to .lenserfight/lenses/unit-test-generator/SKILL.md index 5e9b0fce8..a464fc0e1 100644 --- a/.lenserfight/lenses/unit-test-generator/LENS.MD +++ b/.lenserfight/lenses/unit-test-generator/SKILL.md @@ -1,17 +1,6 @@ --- name: unit-test-generator -title: Unit Test Generator description: Convert changed behavior into focused unit and integration test cases. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: behavior - tool: textarea - required: true -outputs: - kind: checklist -rays: [developer, testing, productivity] --- # Unit Test Generator diff --git a/.lenserfight/lenses/unrestricted-repository-architect/LENS.MD b/.lenserfight/lenses/unrestricted-repository-architect/SKILL.md similarity index 100% rename from .lenserfight/lenses/unrestricted-repository-architect/LENS.MD rename to .lenserfight/lenses/unrestricted-repository-architect/SKILL.md diff --git a/.lenserfight/lenses/validate-output/LENS.MD b/.lenserfight/lenses/validate-output/SKILL.md similarity index 56% rename from .lenserfight/lenses/validate-output/LENS.MD rename to .lenserfight/lenses/validate-output/SKILL.md index bd15c5350..2ab2d2c08 100644 --- a/.lenserfight/lenses/validate-output/LENS.MD +++ b/.lenserfight/lenses/validate-output/SKILL.md @@ -1,17 +1,6 @@ --- name: validate-output -title: Validate Output description: Validate an output against its goal, constraints, audience, and quality bar. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: output - tool: textarea - required: true -outputs: - kind: review -rays: [productivity, analysis] --- # Validate Output diff --git a/.lenserfight/lenses/video-storyboard-planner/LENS.MD b/.lenserfight/lenses/video-storyboard-planner/SKILL.md similarity index 56% rename from .lenserfight/lenses/video-storyboard-planner/LENS.MD rename to .lenserfight/lenses/video-storyboard-planner/SKILL.md index e9d67b89a..8ff12e7a3 100644 --- a/.lenserfight/lenses/video-storyboard-planner/LENS.MD +++ b/.lenserfight/lenses/video-storyboard-planner/SKILL.md @@ -1,17 +1,6 @@ --- name: video-storyboard-planner -title: Video Storyboard Planner description: Turn a script or idea into a shot-by-shot storyboard and production checklist. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: idea - tool: textarea - required: true -outputs: - kind: storyboard -rays: [creator, youtube, multimodal] --- # Video Storyboard Planner diff --git a/.lenserfight/lenses/visual-content-plan/LENS.MD b/.lenserfight/lenses/visual-content-plan/SKILL.md similarity index 55% rename from .lenserfight/lenses/visual-content-plan/LENS.MD rename to .lenserfight/lenses/visual-content-plan/SKILL.md index 307881513..5d0cb17c3 100644 --- a/.lenserfight/lenses/visual-content-plan/LENS.MD +++ b/.lenserfight/lenses/visual-content-plan/SKILL.md @@ -1,17 +1,6 @@ --- name: visual-content-plan -title: Visual Content Plan description: Plan the visuals needed for a campaign, launch, tutorial, or product story. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: campaign_brief - tool: textarea - required: true -outputs: - kind: plan -rays: [creator, multimodal, business] --- # Visual Content Plan diff --git a/.lenserfight/lenses/weekly-operating-review/LENS.MD b/.lenserfight/lenses/weekly-operating-review/SKILL.md similarity index 67% rename from .lenserfight/lenses/weekly-operating-review/LENS.MD rename to .lenserfight/lenses/weekly-operating-review/SKILL.md index 7258e4358..1c6ff8ab9 100644 --- a/.lenserfight/lenses/weekly-operating-review/LENS.MD +++ b/.lenserfight/lenses/weekly-operating-review/SKILL.md @@ -1,23 +1,6 @@ --- name: weekly-operating-review -title: Weekly Operating Review description: Founder-style weekly review with one headline, three wins, three losses, the next bet, and leading-indicator table. -author: '@chainabit' -visibility: public -forkable: true -inputs: - - label: metrics - tool: textarea - required: true - example: Weekly active orgs, retention, revenue, support volume - - label: events - tool: textarea - required: true - example: Shipped new onboarding, lost two enterprise accounts, hired second eng -outputs: - kind: table -rays: [chainabit, productivity, operator, table, template] -seed_uuid: 46000000-0001-0001-0001-000000000001 --- # Weekly Operating Review diff --git a/.lenserfight/lenses/youtube-script-generator/LENS.MD b/.lenserfight/lenses/youtube-script-generator/SKILL.md similarity index 63% rename from .lenserfight/lenses/youtube-script-generator/LENS.MD rename to .lenserfight/lenses/youtube-script-generator/SKILL.md index 71f071e20..3303b17fb 100644 --- a/.lenserfight/lenses/youtube-script-generator/LENS.MD +++ b/.lenserfight/lenses/youtube-script-generator/SKILL.md @@ -1,27 +1,6 @@ --- name: youtube-script-generator -title: YouTube Script Generator description: Writes a structured YouTube video script with hook, value beats, pattern interrupts, and CTA. -author: '@lenserfight' -visibility: public -forkable: true -inputs: - - label: topic - tool: text - required: true - example: How small teams should think about AI evaluations - - label: audience - tool: text - required: true - example: Engineering managers at 20-150 person companies - - label: duration - tool: text - required: true - example: '8' -outputs: - kind: script -rays: [youtube, content, creator, script, template] -seed_uuid: 45000000-0001-0001-0001-000000000001 --- # YouTube Script Generator @@ -44,8 +23,8 @@ YouTube scripts written by AI tend to read like ad-copy: lots of "in today's fas ## Related lenses -- [`blog-outline-generator`](../blog-outline-generator/LENS.MD) — same topic, different medium -- [`ai-image-prompt-builder`](../ai-image-prompt-builder/LENS.MD) — thumbnail concepts +- [`blog-outline-generator`](../blog-outline-generator/SKILL.md) — same topic, different medium +- [`ai-image-prompt-builder`](../ai-image-prompt-builder/SKILL.md) — thumbnail concepts ## Disclaimer diff --git a/.lenserfight/rays/ai-comparison/RAY.MD b/.lenserfight/rays/ai-comparison/SKILL.md similarity index 78% rename from .lenserfight/rays/ai-comparison/RAY.MD rename to .lenserfight/rays/ai-comparison/SKILL.md index 329c35c19..516719c5b 100644 --- a/.lenserfight/rays/ai-comparison/RAY.MD +++ b/.lenserfight/rays/ai-comparison/SKILL.md @@ -1,10 +1,6 @@ --- name: ai-comparison -title: AI Comparison description: Battles and scorecards for comparing model, prompt, lens, and workflow outputs. -visibility: public -route: /ray/ai-comparison -aliases: [model-comparison, evals] --- # `#ai-comparison` diff --git a/.lenserfight/rays/blog/RAY.MD b/.lenserfight/rays/blog/SKILL.md similarity index 73% rename from .lenserfight/rays/blog/RAY.MD rename to .lenserfight/rays/blog/SKILL.md index d0ccc7a2a..e5b9c881e 100644 --- a/.lenserfight/rays/blog/RAY.MD +++ b/.lenserfight/rays/blog/SKILL.md @@ -1,9 +1,6 @@ --- name: blog -title: Blog description: Templates for blog writers — outlines, drafts, SEO, content repurposing. -visibility: public -route: /ray/blog --- # `#blog` @@ -12,12 +9,12 @@ Templates for long-form written content. ## Public lenses -- [`blog-outline-generator`](../../lenses/blog-outline-generator/LENS.MD) +- [`blog-outline-generator`](../../lenses/blog-outline-generator/SKILL.md) ## Public workflows -- [`blog-writer`](../../colenses/blog-writer/COLENS.MD) +- [`blog-writer`](../../colenses/blog-writer/SKILL.md) ## Public battles -- [`blog-vs-youtube-content`](../../battles/blog-vs-youtube-content/BATTLE.MD) +- [`blog-vs-youtube-content`](../../battles/blog-vs-youtube-content/SKILL.md) diff --git a/.lenserfight/rays/business/RAY.MD b/.lenserfight/rays/business/SKILL.md similarity index 81% rename from .lenserfight/rays/business/RAY.MD rename to .lenserfight/rays/business/SKILL.md index b46c75ca3..52fd9d885 100644 --- a/.lenserfight/rays/business/RAY.MD +++ b/.lenserfight/rays/business/SKILL.md @@ -1,10 +1,6 @@ --- name: business -title: Business description: Business planning, KPI, budget, investor update, and operating templates. -visibility: public -route: /ray/business -aliases: [ops, company] --- # `#business` diff --git a/.lenserfight/rays/chainabit/RAY.MD b/.lenserfight/rays/chainabit/SKILL.md similarity index 64% rename from .lenserfight/rays/chainabit/RAY.MD rename to .lenserfight/rays/chainabit/SKILL.md index 45457a529..77cc48d01 100644 --- a/.lenserfight/rays/chainabit/RAY.MD +++ b/.lenserfight/rays/chainabit/SKILL.md @@ -1,9 +1,6 @@ --- name: chainabit -title: Chainabit description: Templates authored by @chainabit — the productivity / BUILD half of the ConectLens ecosystem. -visibility: public -route: /ray/chainabit --- # `#chainabit` @@ -12,15 +9,15 @@ Templates authored by `@chainabit` for startup operators, developer teams, and c ## Public lenses -- [`weekly-operating-review`](../../lenses/weekly-operating-review/LENS.MD) -- [`async-standup-generator`](../../lenses/async-standup-generator/LENS.MD) -- [`pr-triage-brief`](../../lenses/pr-triage-brief/LENS.MD) -- [`launch-content-kit`](../../lenses/launch-content-kit/LENS.MD) -- [`hiring-loop-designer`](../../lenses/hiring-loop-designer/LENS.MD) +- [`weekly-operating-review`](../../lenses/weekly-operating-review/SKILL.md) +- [`async-standup-generator`](../../lenses/async-standup-generator/SKILL.md) +- [`pr-triage-brief`](../../lenses/pr-triage-brief/SKILL.md) +- [`launch-content-kit`](../../lenses/launch-content-kit/SKILL.md) +- [`hiring-loop-designer`](../../lenses/hiring-loop-designer/SKILL.md) ## Public agents -- [`chainabit-operator`](../../lensers/chainabit-operator/LENSER.MD) +- [`chainabit-operator`](../../lensers/chainabit-operator/SKILL.md) ## Ecosystem context diff --git a/.lenserfight/rays/claude/RAY.MD b/.lenserfight/rays/claude/SKILL.md similarity index 70% rename from .lenserfight/rays/claude/RAY.MD rename to .lenserfight/rays/claude/SKILL.md index 4caee6c8e..a3ec6558c 100644 --- a/.lenserfight/rays/claude/RAY.MD +++ b/.lenserfight/rays/claude/SKILL.md @@ -1,9 +1,6 @@ --- name: claude -title: Claude description: Templates designed for or comparing Anthropic Claude models. -visibility: public -route: /ray/claude --- # `#claude` @@ -12,9 +9,9 @@ Templates that target Anthropic Claude as the primary model, or that compare Cla ## Public lenses -- [`ai-output-comparator`](../../lenses/ai-output-comparator/LENS.MD) +- [`ai-output-comparator`](../../lenses/ai-output-comparator/SKILL.md) ## Public battles -- [`claude-vs-openai-pr-review`](../../battles/claude-vs-openai-pr-review/BATTLE.MD) -- [`legal-review-comparison`](../../battles/legal-review-comparison/BATTLE.MD) +- [`claude-vs-openai-pr-review`](../../battles/claude-vs-openai-pr-review/SKILL.md) +- [`legal-review-comparison`](../../battles/legal-review-comparison/SKILL.md) diff --git a/.lenserfight/rays/creator/RAY.MD b/.lenserfight/rays/creator/SKILL.md similarity index 80% rename from .lenserfight/rays/creator/RAY.MD rename to .lenserfight/rays/creator/SKILL.md index d6891c7df..c0a8e21c3 100644 --- a/.lenserfight/rays/creator/RAY.MD +++ b/.lenserfight/rays/creator/SKILL.md @@ -1,10 +1,6 @@ --- name: creator -title: Creator description: Content creation templates for blogs, newsletters, YouTube, social posts, and visual planning. -visibility: public -route: /ray/creator -aliases: [content, editorial] --- # `#creator` diff --git a/.lenserfight/rays/deep-thinking/RAY.MD b/.lenserfight/rays/deep-thinking/SKILL.md similarity index 59% rename from .lenserfight/rays/deep-thinking/RAY.MD rename to .lenserfight/rays/deep-thinking/SKILL.md index e9471767d..3c0d2edc7 100644 --- a/.lenserfight/rays/deep-thinking/RAY.MD +++ b/.lenserfight/rays/deep-thinking/SKILL.md @@ -1,9 +1,6 @@ --- name: deep-thinking -title: Deep Thinking description: Templates that stress-test assumptions and surface second-order effects. -visibility: public -route: /ray/deep-thinking --- # `#deep-thinking` @@ -12,8 +9,8 @@ Templates that push past first-order framing. ## Public lenses -- [`deep-thinking-decision-helper`](../../lenses/deep-thinking-decision-helper/LENS.MD) +- [`deep-thinking-decision-helper`](../../lenses/deep-thinking-decision-helper/SKILL.md) ## Public workflows -- [`startup-planning`](../../colenses/startup-planning/COLENS.MD) — uses deep-thinking as the first node +- [`startup-planning`](../../colenses/startup-planning/SKILL.md) — uses deep-thinking as the first node diff --git a/.lenserfight/rays/developer/RAY.MD b/.lenserfight/rays/developer/SKILL.md similarity index 79% rename from .lenserfight/rays/developer/RAY.MD rename to .lenserfight/rays/developer/SKILL.md index 56d18339e..c709fc5a9 100644 --- a/.lenserfight/rays/developer/RAY.MD +++ b/.lenserfight/rays/developer/SKILL.md @@ -1,10 +1,6 @@ --- name: developer -title: Developer Productivity description: Engineering templates for review, testing, refactoring, architecture, releases, and incidents. -visibility: public -route: /ray/developer -aliases: [engineering, dev] --- # `#developer` diff --git a/.lenserfight/rays/finance/RAY.MD b/.lenserfight/rays/finance/SKILL.md similarity index 84% rename from .lenserfight/rays/finance/RAY.MD rename to .lenserfight/rays/finance/SKILL.md index d05eb1747..c9e29ad0b 100644 --- a/.lenserfight/rays/finance/RAY.MD +++ b/.lenserfight/rays/finance/SKILL.md @@ -1,10 +1,6 @@ --- name: finance -title: Finance description: Finance analysis templates. Analysis only — NOT certified financial advice. -visibility: public -route: /ray/finance -safety: finance_disclaimer_required --- # `#finance` @@ -21,5 +17,5 @@ A pgTAP test fails if a finance-rayed lens's `template_body` does not contain th ## Public lenses -- [`finance-report-explainer`](../../lenses/finance-report-explainer/LENS.MD) -- [`excel-formula-assistant`](../../lenses/excel-formula-assistant/LENS.MD) — when financial data lives in spreadsheets +- [`finance-report-explainer`](../../lenses/finance-report-explainer/SKILL.md) +- [`excel-formula-assistant`](../../lenses/excel-formula-assistant/SKILL.md) — when financial data lives in spreadsheets diff --git a/.lenserfight/rays/gemini/RAY.MD b/.lenserfight/rays/gemini/SKILL.md similarity index 69% rename from .lenserfight/rays/gemini/RAY.MD rename to .lenserfight/rays/gemini/SKILL.md index 9879e7db0..205dd6f81 100644 --- a/.lenserfight/rays/gemini/RAY.MD +++ b/.lenserfight/rays/gemini/SKILL.md @@ -1,9 +1,6 @@ --- name: gemini -title: Gemini description: Templates designed for or comparing Google Gemini models. -visibility: public -route: /ray/gemini --- # `#gemini` @@ -12,8 +9,8 @@ Templates that target Google Gemini as the primary model or include Gemini in a ## Public lenses -- [`ai-output-comparator`](../../lenses/ai-output-comparator/LENS.MD) +- [`ai-output-comparator`](../../lenses/ai-output-comparator/SKILL.md) ## Public battles -- [`legal-review-comparison`](../../battles/legal-review-comparison/BATTLE.MD) +- [`legal-review-comparison`](../../battles/legal-review-comparison/SKILL.md) diff --git a/.lenserfight/rays/github/RAY.MD b/.lenserfight/rays/github/RAY.MD deleted file mode 100644 index 71f2a5fc1..000000000 --- a/.lenserfight/rays/github/RAY.MD +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: github -title: GitHub -description: GitHub-centric templates — pull requests, issue triage, repo automation. -visibility: public -route: /ray/github ---- - -# `#github` - -Templates that operate on GitHub artifacts — pull requests, issues, commits, releases. - -## Public lenses - -- [`code-reviewer`](../../lenses/code-reviewer/LENS.MD) — review a diff -- [`github-issue-solver`](../../lenses/github-issue-solver/LENS.MD) — root cause, fix plan, test plan, and PR draft for a single issue -- [`github-issue-triage`](../../lenses/github-issue-triage/LENS.MD) — classify and prioritize an issue -- [`pr-description-writer`](../../lenses/pr-description-writer/LENS.MD) — write a PR body -- [`pr-triage-brief`](../../lenses/pr-triage-brief/LENS.MD) — triage a review queue - -## Public workflows - -- [`github-issue-solver`](../../colenses/github-issue-solver/COLENS.MD) — end-to-end: triage → analyze → tests → review → PR -- [`pr-review`](../../colenses/pr-review/COLENS.MD) - -## Public lensers - -- [`issue-solver`](../../lensers/issue-solver/LENSER.MD) — autonomous agent: fetch issue → implement → test → PR → merge → close - -## Public battles - -- [`claude-vs-openai-pr-review`](../../battles/claude-vs-openai-pr-review/BATTLE.MD) diff --git a/.lenserfight/rays/github/SKILL.md b/.lenserfight/rays/github/SKILL.md new file mode 100644 index 000000000..1f08240bc --- /dev/null +++ b/.lenserfight/rays/github/SKILL.md @@ -0,0 +1,29 @@ +--- +name: github +description: GitHub-centric templates — pull requests, issue triage, repo automation. +--- + +# `#github` + +Templates that operate on GitHub artifacts — pull requests, issues, commits, releases. + +## Public lenses + +- [`code-reviewer`](../../lenses/code-reviewer/SKILL.md) — review a diff +- [`github-issue-solver`](../../lenses/github-issue-solver/SKILL.md) — root cause, fix plan, test plan, and PR draft for a single issue +- [`github-issue-triage`](../../lenses/github-issue-triage/SKILL.md) — classify and prioritize an issue +- [`pr-description-writer`](../../lenses/pr-description-writer/SKILL.md) — write a PR body +- [`pr-triage-brief`](../../lenses/pr-triage-brief/SKILL.md) — triage a review queue + +## Public workflows + +- [`github-issue-solver`](../../colenses/github-issue-solver/SKILL.md) — end-to-end: triage → analyze → tests → review → PR +- [`pr-review`](../../colenses/pr-review/SKILL.md) + +## Public lensers + +- [`issue-solver`](../../lensers/issue-solver/SKILL.md) — autonomous agent: fetch issue → implement → test → PR → merge → close + +## Public battles + +- [`claude-vs-openai-pr-review`](../../battles/claude-vs-openai-pr-review/SKILL.md) diff --git a/.lenserfight/rays/legal/RAY.MD b/.lenserfight/rays/legal/SKILL.md similarity index 90% rename from .lenserfight/rays/legal/RAY.MD rename to .lenserfight/rays/legal/SKILL.md index df57abd87..092f399f1 100644 --- a/.lenserfight/rays/legal/RAY.MD +++ b/.lenserfight/rays/legal/SKILL.md @@ -1,10 +1,6 @@ --- name: legal -title: Legal description: Legal-adjacent templates. Analysis only — NOT legal advice. -visibility: public -route: /ray/legal -safety: legal_disclaimer_required --- # `#legal` @@ -23,8 +19,8 @@ A pgTAP test fails if a legal-rayed lens's `template_body` does not contain the ## Public lenses -- [`legal-contract-reviewer`](../../lenses/legal-contract-reviewer/LENS.MD) +- [`legal-contract-reviewer`](../../lenses/legal-contract-reviewer/SKILL.md) ## Public battles -- [`legal-review-comparison`](../../battles/legal-review-comparison/BATTLE.MD) +- [`legal-review-comparison`](../../battles/legal-review-comparison/SKILL.md) diff --git a/.lenserfight/rays/multimodal/RAY.MD b/.lenserfight/rays/multimodal/SKILL.md similarity index 81% rename from .lenserfight/rays/multimodal/RAY.MD rename to .lenserfight/rays/multimodal/SKILL.md index 2ce310694..806ed8614 100644 --- a/.lenserfight/rays/multimodal/RAY.MD +++ b/.lenserfight/rays/multimodal/SKILL.md @@ -1,10 +1,6 @@ --- name: multimodal -title: Multimodal description: Image, video, screenshot, diagram, and visual content planning templates. -visibility: public -route: /ray/multimodal -aliases: [visual, media] --- # `#multimodal` diff --git a/.lenserfight/rays/openai/RAY.MD b/.lenserfight/rays/openai/SKILL.md similarity index 69% rename from .lenserfight/rays/openai/RAY.MD rename to .lenserfight/rays/openai/SKILL.md index 52e4d1e75..b19e4f004 100644 --- a/.lenserfight/rays/openai/RAY.MD +++ b/.lenserfight/rays/openai/SKILL.md @@ -1,9 +1,6 @@ --- name: openai -title: OpenAI description: Templates designed for or comparing OpenAI models (GPT-4o, future GPT models). -visibility: public -route: /ray/openai --- # `#openai` @@ -12,8 +9,8 @@ Templates that target OpenAI models or that include OpenAI models in a head-to-h ## Public lenses -- [`ai-output-comparator`](../../lenses/ai-output-comparator/LENS.MD) +- [`ai-output-comparator`](../../lenses/ai-output-comparator/SKILL.md) ## Public battles -- [`claude-vs-openai-pr-review`](../../battles/claude-vs-openai-pr-review/BATTLE.MD) +- [`claude-vs-openai-pr-review`](../../battles/claude-vs-openai-pr-review/SKILL.md) diff --git a/.lenserfight/rays/operations/RAY.MD b/.lenserfight/rays/operations/SKILL.md similarity index 81% rename from .lenserfight/rays/operations/RAY.MD rename to .lenserfight/rays/operations/SKILL.md index 5d7fa1304..3e7ff9cbc 100644 --- a/.lenserfight/rays/operations/RAY.MD +++ b/.lenserfight/rays/operations/SKILL.md @@ -1,10 +1,6 @@ --- name: operations -title: Operations description: Operational templates for releases, incidents, launches, and weekly reviews. -visibility: public -route: /ray/operations -aliases: [ops] --- # `#operations` diff --git a/.lenserfight/rays/productivity/RAY.MD b/.lenserfight/rays/productivity/SKILL.md similarity index 79% rename from .lenserfight/rays/productivity/RAY.MD rename to .lenserfight/rays/productivity/SKILL.md index a0add7a1e..c4bd96160 100644 --- a/.lenserfight/rays/productivity/RAY.MD +++ b/.lenserfight/rays/productivity/SKILL.md @@ -1,9 +1,6 @@ --- name: productivity -title: Productivity description: Daily operating templates — planning, async standups, weekly reviews. -visibility: public -route: /ray/productivity --- # `#productivity` @@ -12,7 +9,7 @@ Operating-system-style templates for daily and weekly cadences. ## Public lenses -- [`daily-productivity-planner`](../../lenses/daily-productivity-planner/LENS.MD) -- [`weekly-operating-review`](../../lenses/weekly-operating-review/LENS.MD) -- [`async-standup-generator`](../../lenses/async-standup-generator/LENS.MD) -- [`excel-formula-assistant`](../../lenses/excel-formula-assistant/LENS.MD) +- [`daily-productivity-planner`](../../lenses/daily-productivity-planner/SKILL.md) +- [`weekly-operating-review`](../../lenses/weekly-operating-review/SKILL.md) +- [`async-standup-generator`](../../lenses/async-standup-generator/SKILL.md) +- [`excel-formula-assistant`](../../lenses/excel-formula-assistant/SKILL.md) diff --git a/.lenserfight/rays/startup/RAY.MD b/.lenserfight/rays/startup/SKILL.md similarity index 63% rename from .lenserfight/rays/startup/RAY.MD rename to .lenserfight/rays/startup/SKILL.md index 1d056ba86..5681a57f9 100644 --- a/.lenserfight/rays/startup/RAY.MD +++ b/.lenserfight/rays/startup/SKILL.md @@ -1,9 +1,6 @@ --- name: startup -title: Startup description: Templates for startup operators — roadmaps, planning, weekly cadence, hiring. -visibility: public -route: /ray/startup --- # `#startup` @@ -12,10 +9,10 @@ Templates aimed at startup founders, operators, and early-stage teams. ## Public lenses -- [`startup-roadmap-designer`](../../lenses/startup-roadmap-designer/LENS.MD) -- [`weekly-operating-review`](../../lenses/weekly-operating-review/LENS.MD) -- [`hiring-loop-designer`](../../lenses/hiring-loop-designer/LENS.MD) +- [`startup-roadmap-designer`](../../lenses/startup-roadmap-designer/SKILL.md) +- [`weekly-operating-review`](../../lenses/weekly-operating-review/SKILL.md) +- [`hiring-loop-designer`](../../lenses/hiring-loop-designer/SKILL.md) ## Public workflows -- [`startup-planning`](../../colenses/startup-planning/COLENS.MD) +- [`startup-planning`](../../colenses/startup-planning/SKILL.md) diff --git a/.lenserfight/rays/youtube/RAY.MD b/.lenserfight/rays/youtube/SKILL.md similarity index 77% rename from .lenserfight/rays/youtube/RAY.MD rename to .lenserfight/rays/youtube/SKILL.md index 9918aac04..6fcd6c0da 100644 --- a/.lenserfight/rays/youtube/RAY.MD +++ b/.lenserfight/rays/youtube/SKILL.md @@ -1,9 +1,6 @@ --- name: youtube -title: YouTube description: Templates for YouTube creators — scripts, thumbnails, production planning. -visibility: public -route: /ray/youtube --- # `#youtube` @@ -12,9 +9,9 @@ Templates that target YouTube creators end-to-end. ## Public lenses -- [`youtube-script-generator`](../../lenses/youtube-script-generator/LENS.MD) -- [`ai-image-prompt-builder`](../../lenses/ai-image-prompt-builder/LENS.MD) — thumbnail concepts +- [`youtube-script-generator`](../../lenses/youtube-script-generator/SKILL.md) +- [`ai-image-prompt-builder`](../../lenses/ai-image-prompt-builder/SKILL.md) — thumbnail concepts ## Public battles -- [`blog-vs-youtube-content`](../../battles/blog-vs-youtube-content/BATTLE.MD) +- [`blog-vs-youtube-content`](../../battles/blog-vs-youtube-content/SKILL.md) diff --git a/apps/cli/src/commands/examples.ts b/apps/cli/src/commands/examples.ts index 8da826383..4eeed5bb9 100644 --- a/apps/cli/src/commands/examples.ts +++ b/apps/cli/src/commands/examples.ts @@ -36,8 +36,8 @@ const EXAMPLES: Example[] = [ category: 'file-workspace', title: 'File workspace — validate and simulate', commands: [ - 'lf validate .lenserfight/lenses/my-lens/LENS.MD', - 'lf workflow run ./COLENS.MD --inputs \'{"topic": "AI Safety"}\'', + 'lf validate .lenserfight/lenses/my-lens/SKILL.md', + 'lf workflow run ./SKILL.md --inputs \'{"topic": "AI Safety"}\'', ], description: 'Markdown objects on disk. No init, Docker, or cloud keys required.', }, diff --git a/apps/cli/src/commands/import.ts b/apps/cli/src/commands/import.ts index cf8737cb6..30f1298c0 100644 --- a/apps/cli/src/commands/import.ts +++ b/apps/cli/src/commands/import.ts @@ -32,8 +32,8 @@ export default defineCommand({ consola.info(' lf import .lenserfight/') consola.info('') consola.info('Generate a template first:') - consola.info(' lf export lens --template --out LENS.MD') - consola.info(' lf export colens --template --out WORKFLOW.MD') + consola.info(' lf export lens --template --out SKILL.md') + consola.info(' lf export colens --template --out SKILL.md') process.exitCode = 1 return } diff --git a/apps/cli/src/commands/migrate-terminology.ts b/apps/cli/src/commands/migrate-terminology.ts index 201333d53..018bb9eea 100644 --- a/apps/cli/src/commands/migrate-terminology.ts +++ b/apps/cli/src/commands/migrate-terminology.ts @@ -7,7 +7,7 @@ import { printJson, printTable } from '../utils/output' export default defineCommand({ meta: { name: 'migrate-terminology', - description: 'Migrate file-mode terminology to lensers/colenses and LENSER.MD/COLENS.MD.', + description: 'Migrate legacy file-mode terminology to lensers/colenses and SKILL.md.', }, args: { apply: { diff --git a/apps/cli/src/commands/template.ts b/apps/cli/src/commands/template.ts index 47d4a97ab..83683df9c 100644 --- a/apps/cli/src/commands/template.ts +++ b/apps/cli/src/commands/template.ts @@ -295,19 +295,19 @@ const listRecurring = defineCommand({ }); // --------------------------------------------------------------------------- -// template submit — validate a community-contributed COLENS.MD template +// template submit — validate a community-contributed SKILL.md template // and emit the gh CLI command the user should paste to open a PR. // --------------------------------------------------------------------------- const submit = defineCommand({ meta: { name: 'submit', description: - 'Validate a COLENS.MD template file and print a gh pr create command to submit it.', + 'Validate a SKILL.md template file and print a gh pr create command to submit it.', }, args: { file: { type: 'positional', - description: 'Path to the COLENS.MD template file', + description: 'Path to the SKILL.md template file', required: true, }, }, @@ -332,7 +332,7 @@ const submit = defineCommand({ const kind = result.document?.frontmatter.kind ?? 'colens'; if (kind !== 'colens' && kind !== 'workflow') { consola.warn( - 'Expected a COLENS.MD (kind=colens) but got kind="%s". Submitting anyway.', + 'Expected a SKILL.md (kind=colens) but got kind="%s". Submitting anyway.', kind ); } diff --git a/apps/cli/src/commands/validate.ts b/apps/cli/src/commands/validate.ts index 70bce09e2..01c9aab61 100644 --- a/apps/cli/src/commands/validate.ts +++ b/apps/cli/src/commands/validate.ts @@ -61,8 +61,8 @@ export default defineCommand({ consola.info(' lf validate my-workflow.md') consola.info('') consola.info('Generate a template first:') - consola.info(' lf export lens --template --out LENS.MD') - consola.info(' lf export colens --template --out WORKFLOW.MD') + consola.info(' lf export lens --template --out SKILL.md') + consola.info(' lf export colens --template --out SKILL.md') process.exitCode = 1 return } diff --git a/apps/cli/src/utils/automation-objects.spec.ts b/apps/cli/src/utils/automation-objects.spec.ts index 0a1303b9b..4b6de196e 100644 --- a/apps/cli/src/utils/automation-objects.spec.ts +++ b/apps/cli/src/utils/automation-objects.spec.ts @@ -447,8 +447,8 @@ Compare useful review outputs. This is not legal advice and must be reviewed by const applied = planTerminologyMigration({ roots: [lf], dryRun: false }) expect(applied.operations.every((operation) => operation.status === 'applied')).toBe(true) - expect(existsSync(join(lf, 'lensers', 'reviewer', 'LENSER.MD'))).toBe(true) - expect(existsSync(join(lf, 'colenses', 'release-flow', 'COLENS.MD'))).toBe(true) + expect(existsSync(join(lf, 'lensers', 'reviewer', 'SKILL.md'))).toBe(true) + expect(existsSync(join(lf, 'colenses', 'release-flow', 'SKILL.md'))).toBe(true) rmSync(root, { recursive: true, force: true }) }) @@ -470,8 +470,8 @@ Compare useful review outputs. This is not legal advice and must be reviewed by const agentTarget = exportAutomationTemplate('agent', undefined, root) const workflowTarget = exportAutomationTemplate('workflow', undefined, root) - expect(agentTarget).toBe(join(root, 'LENSER.MD')) - expect(workflowTarget).toBe(join(root, 'COLENS.MD')) + expect(agentTarget).toBe(join(root, 'SKILL.md')) + expect(workflowTarget).toBe(join(root, 'SKILL.md')) expect(existsSync(agentTarget)).toBe(true) expect(existsSync(workflowTarget)).toBe(true) rmSync(root, { recursive: true, force: true }) diff --git a/apps/cli/src/utils/automation-objects.ts b/apps/cli/src/utils/automation-objects.ts index a38cae782..a516d64e4 100644 --- a/apps/cli/src/utils/automation-objects.ts +++ b/apps/cli/src/utils/automation-objects.ts @@ -17,11 +17,11 @@ import { parse } from 'yaml' import { getLenserfightRuntimeDir } from './local-battle-paths' export const AUTOMATION_FILE_NAMES: Record<AutomationObjectKind, string> = { - lens: 'LENS.MD', - lenser: 'LENSER.MD', - colens: 'COLENS.MD', - battle: 'BATTLE.MD', - ray: 'RAY.MD', + lens: 'SKILL.md', + lenser: 'SKILL.md', + colens: 'SKILL.md', + battle: 'SKILL.md', + ray: 'SKILL.md', team: 'TEAM.MD', agent: 'AGENT.md', agent_team: 'AGENT_TEAM.md', @@ -35,8 +35,22 @@ export const AUTOMATION_FILE_NAMES: Record<AutomationObjectKind, string> = { } const LEGACY_AUTOMATION_FILE_NAMES: Partial<Record<AutomationObjectKind, string[]>> = { - lenser: ['AGENT.MD', 'AGENT.md'], - colens: ['WORKFLOW.MD'], + lens: ['LENS.MD'], + lenser: ['LENSER.MD', 'AGENT.MD', 'AGENT.md'], + colens: ['COLENS.MD', 'WORKFLOW.MD'], + battle: ['BATTLE.MD'], + ray: ['RAY.MD'], +} + +/** Maps canonical directory names to the AutomationObjectKind they contain. */ +const DIRECTORY_TO_KIND: Record<string, AutomationObjectKind> = { + lenses: 'lens', + lensers: 'lenser', + colenses: 'colens', + battles: 'battle', + rays: 'ray', + skills: 'skill', + teams: 'team', } const CANONICAL_TEMPLATE_DIRECTORIES = ['lensers', 'lenses', 'colenses', 'battles', 'rays'] as const @@ -61,6 +75,9 @@ const PRIMARY_FILE_KIND_BY_NAME: Record<string, AutomationObjectKind> = Object.f fileName.toLowerCase(), kind as AutomationObjectKind, ]), + ...Object.entries(LEGACY_AUTOMATION_FILE_NAMES).flatMap(([kind, fileNames]) => + (fileNames ?? []).map((f) => [f.toLowerCase(), kind as AutomationObjectKind]) + ), ['agent.md', 'agent' as AutomationObjectKind], ['workflow.md', 'workflow' as AutomationObjectKind], ] @@ -373,7 +390,7 @@ export function discoverLenserfightWorkspace( const legacyPath = isLegacyAutomationPath(filePath) if (legacyPath) { warnings.push( - `Legacy automation path discovered: ${filePath}. Use ${canonicalKind === 'lenser' ? 'lensers/*/LENSER.MD' : canonicalKind === 'colens' ? 'colenses/*/COLENS.MD' : 'canonical terminology'} for new files.` + `Legacy automation path discovered: ${filePath}. Use ${canonicalKind === 'lenser' ? 'lensers/*/SKILL.md' : canonicalKind === 'colens' ? 'colenses/*/SKILL.md' : 'canonical terminology'} for new files.` ) } discovered.push({ @@ -436,7 +453,17 @@ export function discoverLenserfightWorkspace( } export function inferKindFromFilePath(filePath: string): AutomationObjectKind | undefined { - return PRIMARY_FILE_KIND_BY_NAME[basename(filePath).toLowerCase()] + const fileName = basename(filePath).toLowerCase() + if (fileName === 'skill.md') { + // Infer kind from the canonical directory segment in the path. + const parts = resolve(filePath).split(sep) + for (let i = parts.length - 1; i >= 0; i--) { + const kind = DIRECTORY_TO_KIND[parts[i]] + if (kind !== undefined) return kind + } + return 'skill' + } + return PRIMARY_FILE_KIND_BY_NAME[fileName] } export function resolveUnitRoot(filePath: string): string { @@ -866,10 +893,12 @@ function collectFileRenameOperations(dir: string, operations: TerminologyMigrati collectFileRenameOperations(fullPath, operations) continue } - const targetName = entry.toLowerCase() === 'agent.md' - ? 'LENSER.MD' - : entry.toLowerCase() === 'workflow.md' - ? 'COLENS.MD' + const lower = entry.toLowerCase() + const targetName = + lower === 'agent.md' || lower === 'workflow.md' || + lower === 'lens.md' || lower === 'lenser.md' || + lower === 'colens.md' || lower === 'battle.md' || lower === 'ray.md' + ? 'SKILL.md' : null if (!targetName || entry === targetName) continue pushRenameOperation(operations, fullPath, join(dir, targetName)) @@ -959,37 +988,22 @@ function slugFragment(value: string) { } const LENS_TEMPLATE = `--- -kind: lens -schema_version: 1 -id: lens_<uuid> -slug: market-brief -name: Market Brief Lens -description: Structured task unit for a reusable market brief prompt. -owner: - workspace_id: ws_<uuid> -visibility: workspace -status: draft -version: 0.1.0 -tags: - - research -input_schema: - type: object -output_schema: - type: object -evaluation_refs: [] +name: market-brief +description: Use when you need a structured, reusable prompt for generating market briefs. Accepts a topic and optional context. --- -# Purpose -Explain what this lens is meant to do. +# Market Brief -# Prompt -Write the structured prompt body here. +Produce a concise market brief for \`[[topic]]\` using \`[[context]]\` when provided. -# Inputs -Describe runtime inputs and validation. +## Parameters -# Outputs -Describe the expected output shape and quality bar. +- \`[[topic]]\` — the market or product area to brief +- \`[[context]]\` — optional additional context (company, audience, constraints) + +## Output + +Return a structured brief with: market size, key players, trends, opportunities, and risks. ` const LENSER_TEMPLATE = `--- @@ -1029,10 +1043,7 @@ Describe the final artifact, side effects, and acceptance criteria. const BATTLE_TEMPLATE = `--- name: implementation-battle -description: Use when comparing LENS, COLENS, LENSER, team, model, or human outputs against shared evals. -participants: - - type: lens - ref: ../lenses/example-lens/LENS.MD +description: Use when comparing lens, colens, lenser, team, model, or human outputs against shared evals. --- # Purpose @@ -1049,29 +1060,16 @@ Define the result format and what evidence must be included. ` const RAY_TEMPLATE = `--- -kind: ray -schema_version: 1 -id: ray_<uuid> -slug: developer -name: Developer +name: developer description: Developer productivity, review, release, and architecture templates. -visibility: public -status: active -version: 0.1.0 -route: /ray/developer -aliases: - - engineering -related_item_types: - - lens - - lenser - - colens - - battle --- -# Purpose +# \`#developer\` + +## Purpose Describe the category this ray owns and the kinds of work users should expect. -# Related Items +## Related Items List the highest-signal lenses, lensers, colenses, and battles in this category. # Routing diff --git a/docs/en/explanation/automation/index.md b/docs/en/explanation/automation/index.md index f196834d1..f44606325 100644 --- a/docs/en/explanation/automation/index.md +++ b/docs/en/explanation/automation/index.md @@ -96,10 +96,10 @@ The open-core mode is file-first. Canonical objects live as markdown: - `LENS.md` -- `LENSER.MD` +- `SKILL.md` - `AGENT_TEAM.md` - `TOOL.md` -- `COLENS.MD` +- `SKILL.md` - `PRIVATE_BATTLE.md` - `SKILL.md` - `MEMORY_POLICY.md` diff --git a/docs/en/how-to/agents/run-lenserfighter.md b/docs/en/how-to/agents/run-lenserfighter.md index ac16b26c7..3812a12f8 100644 --- a/docs/en/how-to/agents/run-lenserfighter.md +++ b/docs/en/how-to/agents/run-lenserfighter.md @@ -16,7 +16,7 @@ so every contribution still goes through your normal CI and human review. The runtime is a GitHub Actions workflow ([`.github/workflows/lenserfighter.yml`](https://github.com/conectlens/lenserfight/blob/development/.github/workflows/lenserfighter.yml)) that runs [`anthropics/claude-code-action`](https://github.com/anthropics/claude-code-action) — the same way Claude contributes to GitHub repositories. Its behavior is defined entirely by the -persona file [`.lenserfight/lensers/lenserfighter/LENSER.MD`](https://github.com/conectlens/lenserfight/blob/development/.lenserfight/lensers/lenserfighter/LENSER.MD). +persona file [`.lenserfight/lensers/lenserfighter/SKILL.md`](https://github.com/conectlens/lenserfight/blob/development/.lenserfight/lensers/lenserfighter/SKILL.md). > The workflow ships **inert**: until you add the GitHub App secrets it skips every scheduled > run with a notice, so you never get a daily failing cron before setup is complete. @@ -33,7 +33,7 @@ persona file [`.lenserfight/lensers/lenserfighter/LENSER.MD`](https://github.com | `auto` (cron default) | Rotates the three focuses by day-of-week so cost stays at one action per day. | Varies | It **never** merges, approves, force-pushes, runs migrations, or opens duplicates. See the -[persona file](https://github.com/conectlens/lenserfight/blob/development/.lenserfight/lensers/lenserfighter/LENSER.MD) +[persona file](https://github.com/conectlens/lenserfight/blob/development/.lenserfight/lensers/lenserfighter/SKILL.md) for the complete behavior contract. --- @@ -96,7 +96,7 @@ Watch a few manual runs (start with `review-prs`) before relying on the cron. - **Change cadence:** edit the `schedule.cron` expression. Keep it coarse (daily) — one unit of work per run keeps token and CI cost bounded. - **Change the model / turn budget:** edit `claude_args` (`--model`, `--max-turns`). -- **Change behavior:** edit the persona file `.lenserfight/lensers/lenserfighter/LENSER.MD`. The +- **Change behavior:** edit the persona file `.lenserfight/lensers/lenserfighter/SKILL.md`. The workflow reads it at runtime, so behavior changes do not require touching the workflow. ## Cost diff --git a/docs/en/how-to/cli/sync-file-and-supabase-local.md b/docs/en/how-to/cli/sync-file-and-supabase-local.md index 764426a48..35a550b77 100644 --- a/docs/en/how-to/cli/sync-file-and-supabase-local.md +++ b/docs/en/how-to/cli/sync-file-and-supabase-local.md @@ -16,7 +16,7 @@ This does not target Cloud. For cloud drafts from file battles, use `lf battle f lf sync status # list registry entries lf sync plan # dry-run push plan (requires Supabase local) lf sync push --all # push registry to local Supabase -lf sync push --path ./lenses/my-lens/LENS.MD +lf sync push --path ./lenses/my-lens/SKILL.md lf sync pull --kind lens --id <id> # refresh file from registry export ``` diff --git a/docs/en/how-to/contributors/template-authoring.md b/docs/en/how-to/contributors/template-authoring.md index 0953e1fd2..d563cf511 100644 --- a/docs/en/how-to/contributors/template-authoring.md +++ b/docs/en/how-to/contributors/template-authoring.md @@ -35,9 +35,9 @@ Slugs follow the `content.tags.slug` constraint: Once published, a slug is immutable. Renaming it breaks `/ray/<slug>` links and every shared template URL. -## Step 2 — Write the `LENS.MD` (or `AGENT.MD`, etc.) +## Step 2 — Write the `SKILL.md` (or `AGENT.MD`, etc.) -Create the file at `.lenserfight/lenses/<slug>/LENS.MD` with this frontmatter: +Create the file at `.lenserfight/lenses/<slug>/SKILL.md` with this frontmatter: ```yaml --- @@ -111,7 +111,7 @@ Resolve `v_author` from the reserved handle (`'lenserfight'`, `'chainabit'`, or ## Step 4 — Rays -If your template introduces a ray that does not yet exist, add it to `supabase/migrations/20270812000000_canonical_production_tags.sql` and create a matching `.lenserfight/rays/<slug>/RAY.MD`. Never invent rays in template SQL — always go through the canonical migration. +If your template introduces a ray that does not yet exist, add it to `supabase/migrations/20270812000000_canonical_production_tags.sql` and create a matching `.lenserfight/rays/<slug>/SKILL.md`. Never invent rays in template SQL — always go through the canonical migration. ## Step 5 — Disclaimers (legal / finance only) @@ -165,7 +165,7 @@ seed(<category>): add <slug> template Body checklist: ``` -- [ ] LENS.MD / WORKFLOW.MD / BATTLE.MD / AGENT.MD added under .lenserfight/ +- [ ] SKILL.md / WORKFLOW.MD / SKILL.md / AGENT.MD added under .lenserfight/ - [ ] SQL seed block added to the matching 4*_*templates.sql file - [ ] Rays exist in 20270812000000_canonical_production_tags.sql - [ ] Disclaimer present (if legal / finance) diff --git a/docs/en/lenserfight-file-system.md b/docs/en/lenserfight-file-system.md index d798cae20..6f59d36f3 100644 --- a/docs/en/lenserfight-file-system.md +++ b/docs/en/lenserfight-file-system.md @@ -25,11 +25,12 @@ Tests and automation can set `LENSERFIGHT_HOME` to avoid touching the real `~/.l .lenserfight/ config.json README.md - lensers/*/LENSER.MD - lenses/*/LENS.MD - colenses/*/COLENS.MD - battles/*/BATTLE.MD - rays/*/RAY.MD + lensers/*/SKILL.md + lenses/*/SKILL.md + colenses/*/SKILL.md + battles/*/SKILL.md + rays/*/SKILL.md + skills/*/SKILL.md templates/ # convention for reusable snippets or exported packs examples/ # convention for runnable examples snippets/ # convention for reusable prompt fragments @@ -54,14 +55,14 @@ Only the item folders and referenced `scripts/`, `references/`, `assets/`, and ` 4. Sort paths deterministically. 5. Resolve duplicate item slugs by precedence. -For one-off validation, pass a file or directory: `lf validate .lenserfight/lenses/code-reviewer/LENS.MD`. +For one-off validation, pass a file or directory: `lf validate .lenserfight/lenses/code-reviewer/SKILL.md`. ## Override precedence Highest wins: 1. Runtime CLI flags and explicit command arguments. -2. Item-level metadata in `LENSER.MD`, `LENS.MD`, `COLENS.MD`, `BATTLE.MD`, or `RAY.MD`. +2. Item-level metadata in the item's `SKILL.md` file. 3. Nearest local `.lenserfight` directory. 4. Project-root `.lenserfight` directory. 5. User-global `~/.lenserfight` directory. @@ -123,7 +124,7 @@ lf validate lf validate --json lf validate --no-global lf validate --no-recursive -lf validate .lenserfight/colenses/pr-review/COLENS.MD +lf validate .lenserfight/colenses/pr-review/SKILL.md ``` Validation checks markdown frontmatter, inferred item type, required metadata, known file names, lens parameter declarations, referenced disclosure files, colens references, battle participants, duplicate slugs, deterministic conflict winners, ray/tag references, and legal/finance disclaimer markers. @@ -132,12 +133,12 @@ Validation checks markdown frontmatter, inferred item type, required metadata, k Canonical discovery precedence is deterministic: -1. `lensers/*/LENSER.MD` -2. `colenses/*/COLENS.MD` +1. `lensers/*/SKILL.md` +2. `colenses/*/SKILL.md` 3. `agents/*/AGENT.MD` as a compatibility alias 4. `workflows/*/WORKFLOW.MD` as a compatibility alias -If a canonical and legacy item share the same slug, the canonical path wins and the legacy path is reported as an overridden duplicate. New generators and docs must use only `lensers/`, `colenses/`, `LENSER.MD`, and `COLENS.MD`. +If a canonical and legacy item share the same slug, the canonical path wins and the legacy path is reported as an overridden duplicate. New generators and docs must use only `lensers/`, `colenses/`, `SKILL.md`, and `SKILL.md`. Use `lf migrate-terminology` to preview the rename plan, or `lf migrate-terminology --apply` to rename folders and filenames. The bash helper `scripts/migrate-lenserfight-terminology.sh` provides the same dry-run-first migration path for project, nested, and user-global `.lenserfight` directories. diff --git a/docs/en/platform-setup/index.md b/docs/en/platform-setup/index.md index 23e1d8441..aee2ff76e 100644 --- a/docs/en/platform-setup/index.md +++ b/docs/en/platform-setup/index.md @@ -49,7 +49,7 @@ This lets the TUI dashboard (`lf`) discover all projects on the device without s ## Markdown and JSON automation objects -Automation objects (`LENS.MD`, `LENSER.MD`, `COLENS.MD`, `BATTLE.MD`, `LENSER.MD`, `COLENS.MD`, `TOOL.md`, etc.) are stored as markdown files with YAML frontmatter alongside your code. The local registry at `.lenserfight/automation-registry.json` indexes them. Runtime runs and reports are written to user runtime storage. +Automation objects (`SKILL.md`, `SKILL.md`, `SKILL.md`, `SKILL.md`, `SKILL.md`, `SKILL.md`, `TOOL.md`, etc.) are stored as markdown files with YAML frontmatter alongside your code. The local registry at `.lenserfight/automation-registry.json` indexes them. Runtime runs and reports are written to user runtime storage. ``` .lenserfight/ diff --git a/docs/en/platform-setup/linux.md b/docs/en/platform-setup/linux.md index b590a721d..56c6f4b3a 100644 --- a/docs/en/platform-setup/linux.md +++ b/docs/en/platform-setup/linux.md @@ -118,7 +118,7 @@ pnpm lenserfight validate ./automation > Create a template first if needed: > ```bash -> pnpm lenserfight export agent --template --out ./LENSER.MD +> pnpm lenserfight export agent --template --out ./SKILL.md > ``` ## Run a local battle diff --git a/docs/en/platform-setup/windows.md b/docs/en/platform-setup/windows.md index a620ba0d5..bc43be062 100644 --- a/docs/en/platform-setup/windows.md +++ b/docs/en/platform-setup/windows.md @@ -100,9 +100,9 @@ This file contains secrets — do not commit it. pnpm lenserfight validate .\automation ``` -> If no markdown files exist under `./automation`, create an `LENSER.MD` first: +> If no markdown files exist under `./automation`, create an `SKILL.md` first: > ```powershell -> pnpm lenserfight export agent --template --out .\LENSER.MD +> pnpm lenserfight export agent --template --out .\SKILL.md > ``` ## Run a local battle diff --git a/docs/en/reference/automation/connectlens-agent-skills.md b/docs/en/reference/automation/connectlens-agent-skills.md index 81a0c10ba..afffffd82 100644 --- a/docs/en/reference/automation/connectlens-agent-skills.md +++ b/docs/en/reference/automation/connectlens-agent-skills.md @@ -13,7 +13,7 @@ ConectLens adapts Agent Skills conventions into LenserFight terminology without ## Current State - File-first automation already exists through markdown objects and `lf validate`. -- Native ConectLens primary files are now discovered by filename: `LENS.MD`, `LENSER.MD`, `COLENS.MD`, `BATTLE.MD`, and `TEAM.MD`. +- Native ConectLens primary files are now discovered by filename: `SKILL.md`, `SKILL.md`, `SKILL.md`, `SKILL.md`, and `TEAM.MD`. - Compatibility files remain valid: `SKILL.MD`, `AGENT.MD`, `AGENT_TEAM.md`, `WORKFLOW.MD`, and `PRIVATE_BATTLE.md`. - Parameter placeholders use `[[name]]`; stored database templates may use `[[:uuid]]`. - Lens parameter declarations mirror `lenses.version_parameters`: each declaration needs `label` and `tool_id`. @@ -23,17 +23,17 @@ ConectLens adapts Agent Skills conventions into LenserFight terminology without | Agent Skills term | ConectLens term | Native file | |---|---|---| -| Skill | LENS | `LENS.MD` | -| Agent | LENSER | `LENSER.MD` | -| Workflow | COLENS | `COLENS.MD` | -| Orchestration / comparison | BATTLE | `BATTLE.MD` | +| Skill | LENS | `SKILL.md` | +| Agent | LENSER | `SKILL.md` | +| Workflow | COLENS | `SKILL.md` | +| Orchestration / comparison | BATTLE | `SKILL.md` | | Skill team | Team | `TEAM.MD` | | references | references | `references/` | | scripts | scripts | `scripts/` | | assets | assets | `assets/` | | evals | evals | `evals/` | -`SKILL.MD` can be used as a compatibility wrapper, but `LENS.MD` is the native source of truth. +`SKILL.MD` can be used as a compatibility wrapper, but `SKILL.md` is the native source of truth. ## Package Layout @@ -41,10 +41,10 @@ Use folder-based units: ```txt .lenserfight/ - lenses/example-lens/LENS.MD - lensers/example-lenser/LENSER.MD - colenses/example-colens/COLENS.MD - battles/example-battle/BATTLE.MD + lenses/example-lens/SKILL.md + lensers/example-lenser/SKILL.md + colenses/example-colens/SKILL.md + battles/example-battle/SKILL.md teams/example-team/TEAM.MD ``` @@ -61,7 +61,7 @@ Frontmatter references to these files must be relative to the package root and s ## LENS Rules -A basic `LENS.MD` can stay simple: +A basic `SKILL.md` can stay simple: ```md --- @@ -85,21 +85,21 @@ parameters: ## BATTLE Rules -`BATTLE.MD` is an orchestration document, not a generic skill file. It may reference LENS, COLENS, LENSER, teams, models, humans, evals, scoring, comparison settings, and runtime execution details. +`SKILL.md` is an orchestration document, not a generic skill file. It may reference LENS, COLENS, LENSER, teams, models, humans, evals, scoring, comparison settings, and runtime execution details. A valid battle should declare participants or orchestration references: ```yaml participants: - type: lens - ref: ../lenses/a/LENS.MD + ref: ../lenses/a/SKILL.md - type: lenser - ref: ../lensers/reviewer/LENSER.MD + ref: ../lensers/reviewer/SKILL.md ``` ## Storage Rules -Commit project-safe packages under `.lenserfight/`, such as reusable `LENS.MD` files and their public `references/`, `scripts/`, `assets/`, and `evals/`. +Commit project-safe packages under `.lenserfight/`, such as reusable `SKILL.md` files and their public `references/`, `scripts/`, `assets/`, and `evals/`. Keep private runtime data outside the project: @@ -114,10 +114,10 @@ The CLI writes new local battle state to user runtime storage. Existing `.lenser ## Migration Notes - Move reusable local prompt packages into folder units with native primary files. -- Rename `agents/` to `lensers/`, `workflows/` to `colenses/`, `AGENT.MD` to `LENSER.MD`, and `WORKFLOW.MD` to `COLENS.MD`. -- Compatibility aliases remain readable, but canonical files win mixed-state conflicts and new files must use `lensers/`, `colenses/`, `LENSER.MD`, and `COLENS.MD`. +- Rename `agents/` to `lensers/`, `workflows/` to `colenses/`, `AGENT.MD` to `SKILL.md`, and `WORKFLOW.MD` to `SKILL.md`. +- Compatibility aliases remain readable, but canonical files win mixed-state conflicts and new files must use `lensers/`, `colenses/`, `SKILL.md`, and `SKILL.md`. - Use `lf migrate-terminology` for a dry-run plan or `lf migrate-terminology --apply` to rename safely. The bash helper `scripts/migrate-lenserfight-terminology.sh` supports the same migration for project, nested, and user-global `.lenserfight` directories. -- Keep legacy `SKILL.MD`, `LENSER.MD`, `COLENS.MD`, and `PRIVATE_BATTLE.md` files only while consumers are migrating. +- Keep legacy `SKILL.MD`, `SKILL.md`, `SKILL.md`, and `PRIVATE_BATTLE.md` files only while consumers are migrating. - Do not add secrets to markdown frontmatter, YAML templates, scripts, or examples. - Add `parameters` only when the body uses `[[...]]` placeholders. - Move project-root local battle JSON files out of Git history and into user runtime storage. diff --git a/docs/en/reference/automation/formats/agent-team-md.md b/docs/en/reference/automation/formats/agent-team-md.md index ba5ab1891..f62ad2e13 100644 --- a/docs/en/reference/automation/formats/agent-team-md.md +++ b/docs/en/reference/automation/formats/agent-team-md.md @@ -74,4 +74,4 @@ Delegation, review, conflict resolution, and communication norms. - [Markdown Object Formats overview](../markdown-objects) - [Native `TEAM.MD`](./team-md) -- [Legacy `LENSER.MD`](./lenser-md-legacy) +- [Legacy `SKILL.md`](./lenser-md-legacy) diff --git a/docs/en/reference/automation/formats/battle-md.md b/docs/en/reference/automation/formats/battle-md.md index 3d449f689..bd1cdec46 100644 --- a/docs/en/reference/automation/formats/battle-md.md +++ b/docs/en/reference/automation/formats/battle-md.md @@ -1,19 +1,19 @@ --- -title: BATTLE.MD — Native Comparison Document +title: SKILL.md — Native Comparison Document description: Canonical file format for a ConectLens BATTLE (orchestration / comparison spec). --- -# `BATTLE.MD` — Native orchestration/comparison document +# `SKILL.md` — Native orchestration/comparison document <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> -A **BATTLE** declares a comparison between two or more participants — lenses, lensers, colenses, teams, models, prompts, or humans — under a shared evaluation. `BATTLE.MD` is its native form, validated by `lenserfight validate` and run by `lenserfight battle run`. +A **BATTLE** declares a comparison between two or more participants — lenses, lensers, colenses, teams, models, prompts, or humans — under a shared evaluation. `SKILL.md` is its native form, validated by `lenserfight validate` and run by `lenserfight battle run`. ## Filename -- Canonical: `BATTLE.MD` -- Container: `battles/<slug>/BATTLE.MD` +- Canonical: `SKILL.md` +- Container: `battles/<slug>/SKILL.md` ## Required frontmatter @@ -43,7 +43,7 @@ Discovery walks `participants[]` and `contenders[]`, normalising legacy `agent` ## Canonical template ```bash -lenserfight export battle --template --out .lenserfight/battles/example/BATTLE.MD +lenserfight export battle --template --out .lenserfight/battles/example/SKILL.md ``` ```yaml @@ -52,7 +52,7 @@ name: implementation-battle description: Use when comparing LENS, COLENS, LENSER, team, model, or human outputs against shared evals. participants: - type: lens - ref: ../lenses/example-lens/LENS.MD + ref: ../lenses/example-lens/SKILL.md --- # Purpose @@ -71,11 +71,11 @@ Define the result format and what evidence must be included. ## Running locally ```bash -lenserfight battle run ./BATTLE.MD +lenserfight battle run ./SKILL.md ``` ## Related - [Markdown Object Formats overview](../markdown-objects) - [Portable `PRIVATE_BATTLE.md`](./private-battle-md) -- [Native `LENS.MD`](./lens-md), [`LENSER.MD`](./lenser-md-native), [`COLENS.MD`](./colens-md-native) +- [Native `SKILL.md`](./lens-md), [`SKILL.md`](./lenser-md-native), [`SKILL.md`](./colens-md-native) diff --git a/docs/en/reference/automation/formats/colens-md-legacy.md b/docs/en/reference/automation/formats/colens-md-legacy.md index 9f400732e..71f86c5d0 100644 --- a/docs/en/reference/automation/formats/colens-md-legacy.md +++ b/docs/en/reference/automation/formats/colens-md-legacy.md @@ -1,9 +1,9 @@ --- -title: COLENS.MD (legacy) — Portable Workflow +title: SKILL.md (legacy) — Portable Workflow description: Legacy compatibility alias for a portable workflow with triggers, inputs, steps, and outputs. --- -# `COLENS.MD` — Legacy compatibility alias for a portable workflow +# `SKILL.md` — Legacy compatibility alias for a portable workflow <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> @@ -12,9 +12,9 @@ The legacy portable form of a workflow. Uses `kind: workflow` semantics with str ## Filename -- Canonical: `COLENS.MD` +- Canonical: `SKILL.md` - Legacy alias on disk: `WORKFLOW.MD`, `WORKFLOW.md` → migrated by `lenserfight migrate-terminology` -- Container: `colenses/<slug>/COLENS.MD` (legacy: `workflows/<slug>/WORKFLOW.md`) +- Container: `colenses/<slug>/SKILL.md` (legacy: `workflows/<slug>/WORKFLOW.md`) ## Required frontmatter @@ -78,11 +78,11 @@ Primary outputs, artifacts, and storage destinations. Run `lenserfight migrate-terminology` to: -- Rename `WORKFLOW.md` / `WORKFLOW.MD` → `COLENS.MD` +- Rename `WORKFLOW.md` / `WORKFLOW.MD` → `SKILL.md` - Rename `workflows/` → `colenses/` ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Native `COLENS.MD`](./colens-md-native) +- [Native `SKILL.md`](./colens-md-native) - [Trigger Rule Schema](../trigger-rule-schema) diff --git a/docs/en/reference/automation/formats/colens-md-native.md b/docs/en/reference/automation/formats/colens-md-native.md index 18a920747..c9912cc41 100644 --- a/docs/en/reference/automation/formats/colens-md-native.md +++ b/docs/en/reference/automation/formats/colens-md-native.md @@ -1,21 +1,21 @@ --- -title: COLENS.MD (native) — ConectLens Workflow +title: SKILL.md (native) — ConectLens Workflow description: Canonical file format for a ConectLens COLENS (multi-step workflow). --- -# `COLENS.MD` — Native ConectLens workflow/COLENS +# `SKILL.md` — Native ConectLens workflow/COLENS <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> -A **COLENS** is a ConectLens workflow: a coordinated, multi-step sequence of LENS and LENSER invocations. `COLENS.MD` is its native, file-first form, validated by `lenserfight validate` and run by `lenserfight workflow run`. +A **COLENS** is a ConectLens workflow: a coordinated, multi-step sequence of LENS and LENSER invocations. `SKILL.md` is its native, file-first form, validated by `lenserfight validate` and run by `lenserfight workflow run`. ## Filename -- Canonical: `COLENS.MD` -- Container: `colenses/<slug>/COLENS.MD` +- Canonical: `SKILL.md` +- Container: `colenses/<slug>/SKILL.md` - Legacy alias recognised by discovery: `WORKFLOW.MD` -- `lenserfight migrate-terminology` renames `WORKFLOW.md` → `COLENS.MD` and `workflows/` → `colenses/`. +- `lenserfight migrate-terminology` renames `WORKFLOW.md` → `SKILL.md` and `workflows/` → `colenses/`. ## Required frontmatter @@ -44,7 +44,7 @@ When frontmatter declares `nodes[]` or `steps[]`, each step's `lens:` or `lenser ## Canonical template ```bash -lenserfight export colens --template --out .lenserfight/colenses/example/COLENS.MD +lenserfight export colens --template --out .lenserfight/colenses/example/SKILL.md ``` ```yaml @@ -71,7 +71,7 @@ Describe the final artifact, side effects, and acceptance criteria. ## Running locally ```bash -lenserfight workflow run .lenserfight/colenses/example/COLENS.MD +lenserfight workflow run .lenserfight/colenses/example/SKILL.md ``` The runner produces a `RUN_REPORT.md` under the user runtime workspace (not `.lenserfight/`). @@ -79,6 +79,6 @@ The runner produces a `RUN_REPORT.md` under the user runtime workspace (not `.le ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Legacy `COLENS.MD` (portable workflow)](./colens-md-legacy) -- [Native `LENSER.MD`](./lenser-md-native) -- [Native `BATTLE.MD`](./battle-md) +- [Legacy `SKILL.md` (portable workflow)](./colens-md-legacy) +- [Native `SKILL.md`](./lenser-md-native) +- [Native `SKILL.md`](./battle-md) diff --git a/docs/en/reference/automation/formats/evaluation-md.md b/docs/en/reference/automation/formats/evaluation-md.md index 72975c807..31de75af1 100644 --- a/docs/en/reference/automation/formats/evaluation-md.md +++ b/docs/en/reference/automation/formats/evaluation-md.md @@ -73,6 +73,6 @@ Describe rubric scoring, judge agent use, and human overrides. ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Native `BATTLE.MD`](./battle-md) +- [Native `SKILL.md`](./battle-md) - [Portable `PRIVATE_BATTLE.md`](./private-battle-md) - [Portable `RUN_REPORT.md`](./run-report-md) diff --git a/docs/en/reference/automation/formats/lens-md-legacy.md b/docs/en/reference/automation/formats/lens-md-legacy.md index 8b4529dac..e3422691d 100644 --- a/docs/en/reference/automation/formats/lens-md-legacy.md +++ b/docs/en/reference/automation/formats/lens-md-legacy.md @@ -8,12 +8,12 @@ description: Legacy portable form of a lens/task unit with full strict frontmatt <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> -The legacy portable form of a lens. Identical filename to the native form (`LENS.MD` — discovery is case-insensitive), but uses the **full** frontmatter schema (`kind`, `schema_version`, `id`, …) plus the strict section structure. Use this when interchanging lenses between tools or when stricter validation is needed. +The legacy portable form of a lens. Identical filename to the native form (`SKILL.md` — discovery is case-insensitive), but uses the **full** frontmatter schema (`kind`, `schema_version`, `id`, …) plus the strict section structure. Use this when interchanging lenses between tools or when stricter validation is needed. ## Filename -- Canonical: `LENS.MD` / `LENS.md` -- Container: `lenses/<slug>/LENS.MD` +- Canonical: `SKILL.md` / `LENS.md` +- Container: `lenses/<slug>/SKILL.md` ## Required frontmatter @@ -89,4 +89,4 @@ evaluation_refs: [] ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Native `LENS.MD`](./lens-md) +- [Native `SKILL.md`](./lens-md) diff --git a/docs/en/reference/automation/formats/lens-md.md b/docs/en/reference/automation/formats/lens-md.md index 840205c79..14b47d961 100644 --- a/docs/en/reference/automation/formats/lens-md.md +++ b/docs/en/reference/automation/formats/lens-md.md @@ -1,19 +1,19 @@ --- -title: LENS.MD — Native ConectLens Lens +title: SKILL.md — Native ConectLens Lens description: Canonical file format for a ConectLens lens (reusable task unit). --- -# `LENS.MD` — Native ConectLens lens/task unit +# `SKILL.md` — Native ConectLens lens/task unit <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> -`LENS.MD` is the canonical, file-first representation of a **lens**: a reusable prompt/task unit with a structured body and optional parameter contract. It is the native ConectLens form, validated by `lenserfight validate`, exported by `lenserfight export lens`, and consumed by `lenserfight workflow run`. +`SKILL.md` is the canonical, file-first representation of a **lens**: a reusable prompt/task unit with a structured body and optional parameter contract. It is the native ConectLens form, validated by `lenserfight validate`, exported by `lenserfight export lens`, and consumed by `lenserfight workflow run`. ## Filename -- Canonical: `LENS.MD` (upper-case `.MD`) -- Container directory: `lenses/<slug>/LENS.MD` (or any path on disk; folder containment matters for progressive disclosure) +- Canonical: `SKILL.md` (upper-case `.MD`) +- Container directory: `lenses/<slug>/SKILL.md` (or any path on disk; folder containment matters for progressive disclosure) - Lookup: case-insensitive — discovery normalises file names through `PRIMARY_FILE_KIND_BY_NAME` in [automation-objects.ts](../../../../../../apps/cli/src/utils/automation-objects.ts). ## Required frontmatter @@ -57,7 +57,7 @@ Native compact lenses (only `name` and `description`) skip section checks. ## Canonical template ```bash -lenserfight export lens --template --out .lenserfight/lenses/example/LENS.MD +lenserfight export lens --template --out .lenserfight/lenses/example/SKILL.md ``` ```yaml diff --git a/docs/en/reference/automation/formats/lenser-md-legacy.md b/docs/en/reference/automation/formats/lenser-md-legacy.md index 1d9193234..239b779c1 100644 --- a/docs/en/reference/automation/formats/lenser-md-legacy.md +++ b/docs/en/reference/automation/formats/lenser-md-legacy.md @@ -1,20 +1,20 @@ --- -title: LENSER.MD (legacy) — Portable Agent Definition +title: SKILL.md (legacy) — Portable Agent Definition description: Legacy compatibility alias for a portable agent definition. --- -# `LENSER.MD` — Legacy compatibility alias for a portable agent definition +# `SKILL.md` — Legacy compatibility alias for a portable agent definition <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> -In the legacy portable model, `LENSER.MD` is the canonical filename for a full **agent** definition: metadata, instructions, permissions, model/tool policy, memory policy reference. It exists for compatibility with tools that emit the older `kind: agent` schema; discovery accepts it as an alias. +In the legacy portable model, `SKILL.md` is the canonical filename for a full **agent** definition: metadata, instructions, permissions, model/tool policy, memory policy reference. It exists for compatibility with tools that emit the older `kind: agent` schema; discovery accepts it as an alias. ## Filename -- Canonical: `LENSER.MD` +- Canonical: `SKILL.md` - Legacy aliases on disk: `AGENT.MD`, `AGENT.md` → migrated by `lenserfight migrate-terminology` -- Container: `lensers/<slug>/LENSER.MD` (legacy: `agents/<slug>/AGENT.md`) +- Container: `lensers/<slug>/SKILL.md` (legacy: `agents/<slug>/AGENT.md`) ## Required frontmatter @@ -84,7 +84,7 @@ allowed_actions: [read, suggest, draft] Run `lenserfight migrate-terminology` to: -- Rename `AGENT.md` / `AGENT.MD` → `LENSER.MD` +- Rename `AGENT.md` / `AGENT.MD` → `SKILL.md` - Rename `agents/` → `lensers/` Then optionally convert to compact native frontmatter (just `name` + `description`). @@ -92,4 +92,4 @@ Then optionally convert to compact native frontmatter (just `name` + `descriptio ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Native `LENSER.MD`](./lenser-md-native) +- [Native `SKILL.md`](./lenser-md-native) diff --git a/docs/en/reference/automation/formats/lenser-md-native.md b/docs/en/reference/automation/formats/lenser-md-native.md index aa7d09216..ad3dded31 100644 --- a/docs/en/reference/automation/formats/lenser-md-native.md +++ b/docs/en/reference/automation/formats/lenser-md-native.md @@ -1,21 +1,21 @@ --- -title: LENSER.MD (native) — ConectLens Agent +title: SKILL.md (native) — ConectLens Agent description: Canonical file format for a ConectLens LENSER (agent definition). --- -# `LENSER.MD` — Native ConectLens agent/LENSER definition +# `SKILL.md` — Native ConectLens agent/LENSER definition <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> -A **LENSER** is ConectLens's term for an agent: a persistent operator with a mission, activation rules, and operating constraints. `LENSER.MD` is its native, file-first form, validated by `lenserfight validate` and exported by `lenserfight export lenser`. +A **LENSER** is ConectLens's term for an agent: a persistent operator with a mission, activation rules, and operating constraints. `SKILL.md` is its native, file-first form, validated by `lenserfight validate` and exported by `lenserfight export lenser`. ## Filename -- Canonical: `LENSER.MD` -- Container: `lensers/<slug>/LENSER.MD` +- Canonical: `SKILL.md` +- Container: `lensers/<slug>/SKILL.md` - Legacy aliases recognised by discovery: `AGENT.MD`, `AGENT.md` (see `LEGACY_AUTOMATION_FILE_NAMES` in [automation-objects.ts](../../../../../../apps/cli/src/utils/automation-objects.ts)) -- The `lenserfight migrate-terminology` command renames `AGENT.md` → `LENSER.MD` and `agents/` → `lensers/`. +- The `lenserfight migrate-terminology` command renames `AGENT.md` → `SKILL.md` and `agents/` → `lensers/`. ## Required frontmatter @@ -46,7 +46,7 @@ Compact native LENSERs (only `name` + `description`) skip section checks. ## Canonical template ```bash -lenserfight export lenser --template --out .lenserfight/lensers/example/LENSER.MD +lenserfight export lenser --template --out .lenserfight/lensers/example/SKILL.md ``` ```yaml @@ -69,7 +69,7 @@ Define boundaries, safety checks, scripts, references, and handoff expectations. ``` lensers/<slug>/ - LENSER.MD + SKILL.md references/ # markdown notes the LENSER reads on demand scripts/ # non-interactive helper scripts assets/ # static files @@ -79,6 +79,6 @@ lensers/<slug>/ ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Legacy `LENSER.MD` (portable agent definition)](./lenser-md-legacy) +- [Legacy `SKILL.md` (portable agent definition)](./lenser-md-legacy) - [Native `TEAM.MD`](./team-md) - Implementation: [automation-objects.ts](../../../../../../apps/cli/src/utils/automation-objects.ts) diff --git a/docs/en/reference/automation/formats/memory-policy-md.md b/docs/en/reference/automation/formats/memory-policy-md.md index 0052566be..178612542 100644 --- a/docs/en/reference/automation/formats/memory-policy-md.md +++ b/docs/en/reference/automation/formats/memory-policy-md.md @@ -69,4 +69,4 @@ Sensitive data, noisy transcripts, low-confidence claims, and temporary failures ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Legacy `LENSER.MD`](./lenser-md-legacy) (references memory policies via `memory_policy_ref`) +- [Legacy `SKILL.md`](./lenser-md-legacy) (references memory policies via `memory_policy_ref`) diff --git a/docs/en/reference/automation/formats/private-battle-md.md b/docs/en/reference/automation/formats/private-battle-md.md index 8a7501266..c5095fbec 100644 --- a/docs/en/reference/automation/formats/private-battle-md.md +++ b/docs/en/reference/automation/formats/private-battle-md.md @@ -8,7 +8,7 @@ description: Portable comparison spec with participants, evaluation, and report <ExperimentalBadge title="Automation" description="This area is under active construction. File formats, APIs and runtime behaviour may shift without notice — try it, but treat it as pre-stable." /> -The portable form of a battle. Used for **workspace-private** comparisons (`kind: private_battle`), as opposed to publicly published battles or the native `BATTLE.MD`. Run with `lenserfight battle run ./PRIVATE_BATTLE.md`. +The portable form of a battle. Used for **workspace-private** comparisons (`kind: private_battle`), as opposed to publicly published battles or the native `SKILL.md`. Run with `lenserfight battle run ./PRIVATE_BATTLE.md`. ## Filename @@ -74,6 +74,6 @@ Required sections in the exported report. ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Native `BATTLE.MD`](./battle-md) +- [Native `SKILL.md`](./battle-md) - [Portable `EVALUATION.md`](./evaluation-md) - [Portable `RUN_REPORT.md`](./run-report-md) diff --git a/docs/en/reference/automation/formats/run-report-md.md b/docs/en/reference/automation/formats/run-report-md.md index ab64685a9..de0ab7589 100644 --- a/docs/en/reference/automation/formats/run-report-md.md +++ b/docs/en/reference/automation/formats/run-report-md.md @@ -65,6 +65,6 @@ Summarize outputs, failures, and next actions. ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Native `COLENS.MD`](./colens-md-native) -- [Native `BATTLE.MD`](./battle-md) +- [Native `SKILL.md`](./colens-md-native) +- [Native `SKILL.md`](./battle-md) - [Portable `EVALUATION.md`](./evaluation-md) diff --git a/docs/en/reference/automation/formats/skill-md.md b/docs/en/reference/automation/formats/skill-md.md index 44f38d640..6de647e56 100644 --- a/docs/en/reference/automation/formats/skill-md.md +++ b/docs/en/reference/automation/formats/skill-md.md @@ -70,4 +70,4 @@ Step-by-step instructions the lenser should follow. - [Markdown Object Formats overview](../markdown-objects) - [ConectLens Agent Skills Ruleset](../ConectLens-agent-skills) -- [Native `LENSER.MD`](./lenser-md-native) +- [Native `SKILL.md`](./lenser-md-native) diff --git a/docs/en/reference/automation/formats/team-md.md b/docs/en/reference/automation/formats/team-md.md index 7a886d8ec..b4cf98b9e 100644 --- a/docs/en/reference/automation/formats/team-md.md +++ b/docs/en/reference/automation/formats/team-md.md @@ -60,4 +60,4 @@ Define delegation, review, conflict resolution, and escalation rules. - [Markdown Object Formats overview](../markdown-objects) - [Portable `AGENT_TEAM.md`](./agent-team-md) -- [Native `LENSER.MD`](./lenser-md-native) +- [Native `SKILL.md`](./lenser-md-native) diff --git a/docs/en/reference/automation/formats/tool-md.md b/docs/en/reference/automation/formats/tool-md.md index 3669e43c7..e4f75b4a8 100644 --- a/docs/en/reference/automation/formats/tool-md.md +++ b/docs/en/reference/automation/formats/tool-md.md @@ -82,4 +82,4 @@ Timeout, rate limit, auth error, malformed upstream data, and empty result. ## Related - [Markdown Object Formats overview](../markdown-objects) -- [Native `LENS.MD`](./lens-md) (lenses call tools via `parameters[i].tool_id`) +- [Native `SKILL.md`](./lens-md) (lenses call tools via `parameters[i].tool_id`) diff --git a/docs/en/reference/automation/markdown-objects.md b/docs/en/reference/automation/markdown-objects.md index 6077b533b..48fbc213c 100644 --- a/docs/en/reference/automation/markdown-objects.md +++ b/docs/en/reference/automation/markdown-objects.md @@ -34,16 +34,16 @@ tags: [] | Format | Purpose | Required fields | Validation | |---|---|---|---| -| [`LENS.MD`](./formats/lens-md) | Native ConectLens lens/task unit | `name`, `description`; parameterized files also need `parameters[].label` + `tool_id` | frontmatter + parameter + disclosure checks | -| [`LENSER.MD`](./formats/lenser-md-native) | Native ConectLens agent/LENSER definition | `name`, `description` | frontmatter + disclosure checks | -| [`COLENS.MD`](./formats/colens-md-native) | Native ConectLens workflow/COLENS | `name`, `description` | frontmatter + disclosure checks | -| [`BATTLE.MD`](./formats/battle-md) | Native orchestration/comparison document | `name`, `description`, participants or orchestration references | frontmatter + battle reference checks | +| [`SKILL.md`](./formats/lens-md) | Native ConectLens lens/task unit | `name`, `description`; parameterized files also need `parameters[].label` + `tool_id` | frontmatter + parameter + disclosure checks | +| [`SKILL.md`](./formats/lenser-md-native) | Native ConectLens agent/LENSER definition | `name`, `description` | frontmatter + disclosure checks | +| [`SKILL.md`](./formats/colens-md-native) | Native ConectLens workflow/COLENS | `name`, `description` | frontmatter + disclosure checks | +| [`SKILL.md`](./formats/battle-md) | Native orchestration/comparison document | `name`, `description`, participants or orchestration references | frontmatter + battle reference checks | | [`TEAM.MD`](./formats/team-md) | Native LENSER team definition | `name`, `description` | frontmatter + disclosure checks | | [`LENS.md`](./formats/lens-md-legacy) | Legacy portable lens/task unit | `id`, `name`, prompt body, input/output schema | frontmatter + section checks | -| [`LENSER.MD`](./formats/lenser-md-legacy) | Legacy compatibility alias for a portable agent definition | metadata, instructions, permissions | frontmatter + section checks | +| [`SKILL.md`](./formats/lenser-md-legacy) | Legacy compatibility alias for a portable agent definition | metadata, instructions, permissions | frontmatter + section checks | | [`AGENT_TEAM.md`](./formats/agent-team-md) | Portable team definition | members, purpose, collaboration rules | frontmatter + section checks | | [`TOOL.md`](./formats/tool-md) | Portable tool contract | input/output schema, auth, risk | frontmatter + section checks | -| [`COLENS.MD`](./formats/colens-md-legacy) | Legacy compatibility alias for a portable workflow | triggers, inputs, steps, outputs | frontmatter + section checks | +| [`SKILL.md`](./formats/colens-md-legacy) | Legacy compatibility alias for a portable workflow | triggers, inputs, steps, outputs | frontmatter + section checks | | [`PRIVATE_BATTLE.md`](./formats/private-battle-md) | Portable comparison spec | participants, evaluation, report | frontmatter + section checks | | [`SKILL.md`](./formats/skill-md) | Portable reusable capability | purpose, when to use, workflow | frontmatter + section checks | | [`MEMORY_POLICY.md`](./formats/memory-policy-md) | Portable memory rules | scope, retention, promotion | frontmatter + section checks | @@ -57,13 +57,13 @@ The current CLI foundation supports: ```bash lenserfight validate ./automation lenserfight import ./automation -lenserfight export lens --template --out .lenserfight/lenses/example/LENS.MD -lenserfight export lenser --template --out .lenserfight/lensers/example/LENSER.MD -lenserfight export colens --template --out .lenserfight/colenses/example/COLENS.MD -lenserfight export battle --template --out .lenserfight/battles/example/BATTLE.MD +lenserfight export lens --template --out .lenserfight/lenses/example/SKILL.md +lenserfight export lenser --template --out .lenserfight/lensers/example/SKILL.md +lenserfight export colens --template --out .lenserfight/colenses/example/SKILL.md +lenserfight export battle --template --out .lenserfight/battles/example/SKILL.md lenserfight migrate-terminology lenserfight migrate-terminology --apply -lenserfight workflow run .lenserfight/colenses/example/COLENS.MD +lenserfight workflow run .lenserfight/colenses/example/SKILL.md lenserfight tool test ./TOOL.md lenserfight evaluate ./EVALUATION.md lenserfight battle run ./PRIVATE_BATTLE.md @@ -75,7 +75,7 @@ lenserfight battle run ./PRIVATE_BATTLE.md - `lenserfight import` indexes validated files into a local registry - `lenserfight export <kind> <id>` re-emits an imported object - `lenserfight export <kind> --template` writes a canonical starter template -- legacy `agent` and `workflow` template requests write canonical `LENSER.MD` and `COLENS.MD` unless `--legacy` is passed +- legacy `agent` and `workflow` template requests write canonical `SKILL.md` and `SKILL.md` unless `--legacy` is passed ## Design rules diff --git a/docs/en/reference/cli/automation.md b/docs/en/reference/cli/automation.md index 8393c4e28..b98af3e59 100644 --- a/docs/en/reference/cli/automation.md +++ b/docs/en/reference/cli/automation.md @@ -10,7 +10,7 @@ The automation-first CLI surface is the local-file companion to LenserFight's ca | `lf import <path>` | Register validated markdown objects in the local registry | | `lf export <kind> --template` | Generate a canonical object template | | `lf export <kind> <id>` | Re-export an imported object by id | -| `lf workflow run <file>` | Simulate a `COLENS.MD` and emit reports | +| `lf workflow run <file>` | Simulate a `SKILL.md` and emit reports | | `lf tool test <file>` | Validate a `TOOL.md` contract | | `lf evaluate <file>` | Validate and summarize an `EVALUATION.md` spec | | `lf battle run <file>` | Simulate a `PRIVATE_BATTLE.md` spec | @@ -19,11 +19,11 @@ The automation-first CLI surface is the local-file companion to LenserFight's ca ## Typical local-first flow ```bash -lenserfight export agent --template --out ./LENSER.MD -lenserfight export workflow --template --out ./COLENS.MD +lenserfight export agent --template --out ./SKILL.md +lenserfight export workflow --template --out ./SKILL.md lenserfight validate . lenserfight import . -lenserfight workflow run ./COLENS.MD +lenserfight workflow run ./SKILL.md lenserfight battle run ./PRIVATE_BATTLE.md ``` diff --git a/docs/en/reference/cli/index.md b/docs/en/reference/cli/index.md index 48009394a..9fc38bf3f 100644 --- a/docs/en/reference/cli/index.md +++ b/docs/en/reference/cli/index.md @@ -311,7 +311,7 @@ See [`lf policy`](policy.md), [`lf budget`](budget.md), [`lf kill-switch`](kill- | Command | Description | |---------|-------------| -| `lf migrate-terminology` | Rewrite legacy `AGENT.md`/`WORKFLOW.md` to canonical `LENSER.MD`/`COLENS.MD` (dry-run by default) | +| `lf migrate-terminology` | Rewrite legacy `AGENT.md`/`WORKFLOW.md` to canonical `SKILL.md`/`SKILL.md` (dry-run by default) | | `lf whats-new [--n N]` | Print recent CHANGELOG entries | | `lf onboard` | Friendly alias for `lf setup` — same behavior, gentler name | diff --git a/docs/en/reference/cli/migrate-terminology.md b/docs/en/reference/cli/migrate-terminology.md index bb8bb1c51..75a192bf9 100644 --- a/docs/en/reference/cli/migrate-terminology.md +++ b/docs/en/reference/cli/migrate-terminology.md @@ -1,11 +1,11 @@ --- title: lf migrate-terminology -description: Migrate legacy file-mode terminology (AGENT.md, WORKFLOW.md) to the canonical lensers/colenses vocabulary (LENSER.MD, COLENS.MD). +description: Migrate legacy file-mode terminology (AGENT.md, WORKFLOW.md) to the canonical lensers/colenses vocabulary (SKILL.md, SKILL.md). --- # `lf migrate-terminology` -Rewrite legacy file-mode terminology in any `.lenserfight/` tree from `AGENT.md` / `WORKFLOW.md` to the canonical `LENSER.MD` / `COLENS.MD`. Dry-run by default — nothing is touched unless you pass `--apply`. +Rewrite legacy file-mode terminology in any `.lenserfight/` tree from `AGENT.md` / `WORKFLOW.md` to the canonical `SKILL.md` / `SKILL.md`. Dry-run by default — nothing is touched unless you pass `--apply`. ```bash lf migrate-terminology # dry-run plan (default) @@ -32,11 +32,11 @@ By default the command discovers every `.lenserfight/` tree at or beneath the cu ``` op from to status -rename AGENT.md LENSER.MD ok -rename WORKFLOW.md COLENS.MD ok -rewrite COLENS.MD (terminology) ok -skip LENSER.MD (already-canonical) skipped -conflict AGENT.md LENSER.MD conflict (both files exist) +rename AGENT.md SKILL.md ok +rename WORKFLOW.md SKILL.md ok +rewrite SKILL.md (terminology) ok +skip SKILL.md (already-canonical) skipped +conflict AGENT.md SKILL.md conflict (both files exist) ``` - `ok` operations will be applied with `--apply`. diff --git a/docs/en/reference/cli/workflow.md b/docs/en/reference/cli/workflow.md index ed8c7a04d..f4cbd4ed8 100644 --- a/docs/en/reference/cli/workflow.md +++ b/docs/en/reference/cli/workflow.md @@ -27,7 +27,7 @@ Manage file-based and cloud Workflows. Use `lf workflow run` for local simulatio ## `lf workflow run` -Parse a local `WORKFLOW.md` or `COLENS.MD`, classify each step by executability, and emit a JSON + Markdown run report. +Parse a local `WORKFLOW.md` or `SKILL.md`, classify each step by executability, and emit a JSON + Markdown run report. ```bash lf workflow run <file> [--inputs <json>] [--json] @@ -37,7 +37,7 @@ lf workflow run <file> [--inputs <json>] [--json] | Argument | Type | Required | Description | |---|---|---|---| -| `file` | positional | yes | Path to `WORKFLOW.md` or `COLENS.MD` | +| `file` | positional | yes | Path to `WORKFLOW.md` or `SKILL.md` | ### Flags @@ -87,7 +87,7 @@ lf workflow validate <file> [--json] | Argument | Type | Required | Description | |---|---|---|---| -| `file` | positional | yes | Path to `WORKFLOW.md` or `COLENS.MD` | +| `file` | positional | yes | Path to `WORKFLOW.md` or `SKILL.md` | ### Flags diff --git a/docs/en/reference/storage-architecture.md b/docs/en/reference/storage-architecture.md index 6a097b128..057e39378 100644 --- a/docs/en/reference/storage-architecture.md +++ b/docs/en/reference/storage-architecture.md @@ -59,7 +59,7 @@ LenserFight loads environment variables in this order. Later sources override ea 7. `~/.lenserfight/.env.tokens` (gitignored, secret-only) 8. Process environment variables (highest precedence) -Tokens live exclusively in layers 6, 7, and 8. Templates (`LENS.MD`, `COLENS.MD`, `BATTLE.MD`, YAML, JSON) must never contain raw token values — they reference variable names only. +Tokens live exclusively in layers 6, 7, and 8. Templates (`SKILL.md`, `SKILL.md`, `SKILL.md`, YAML, JSON) must never contain raw token values — they reference variable names only. ## Battle storage separation @@ -67,7 +67,7 @@ The legacy `.lenserfight/local-battles/<id>.json` path mixed portable battle def | Concept | Path | Layer | | -------------------------------- | ------------------------------------------------- | ---------- | -| Battle template definition | `.lenserfight/battles/<slug>/BATTLE.MD` | Portable | +| Battle template definition | `.lenserfight/battles/<slug>/SKILL.md` | Portable | | Battle config (rubric, scoring) | `.lenserfight/battles/<slug>/config.yaml` | Portable | | Battle execution trace | `~/.lenserfight/runtime/battles/<battle-id>/` | Runtime | | Cached AI responses for a battle | `~/.lenserfight/cache/ai-responses/` | Runtime | @@ -79,14 +79,14 @@ Any tool that reads or writes battle data MUST honour this split. Migration of l LenserFight belongs to the **ConectLens** ecosystem. The filesystem layout preserves ConectLens vocabulary in the canonical filename: -- `LENS.MD` — prompt asset (ConectLens-native) -- `LENSER.MD` — owner profile (reserved, not yet exported) -- `LENSER.MD` — configured AI lenser -- `COLENS.MD` — DAG of lenses -- `BATTLE.MD` — scored competition -- `RAY.MD` — discovery ray +- `SKILL.md` — prompt asset (ConectLens-native) +- `SKILL.md` — owner profile (reserved, not yet exported) +- `SKILL.md` — configured AI lenser +- `SKILL.md` — DAG of lenses +- `SKILL.md` — scored competition +- `SKILL.md` — discovery ray -`SKILL.MD` is supported as an industry-compatibility alias for `LENS.MD` because many OSS AI ecosystems (Claude Code, agentskills.io, others) standardise on `SKILL.MD` for the same concept. When both files exist for the same template they MUST contain byte-identical content; the recommended pattern is to keep `LENS.MD` as the source and `SKILL.MD` as a generated mirror created by `lf doctor sync-aliases`. +`SKILL.MD` is supported as an industry-compatibility alias for `SKILL.md` because many OSS AI ecosystems (Claude Code, agentskills.io, others) standardise on `SKILL.MD` for the same concept. When both files exist for the same template they MUST contain byte-identical content; the recommended pattern is to keep `SKILL.md` as the source and `SKILL.MD` as a generated mirror created by `lf doctor sync-aliases`. ## How the database mirrors this tree @@ -94,11 +94,11 @@ Every public template in the database has a 1:1 sibling under `.lenserfight/` ke | DB table | Mirrored at | | --------------------- | ------------------------------------ | -| `lenses.lenses` | `.lenserfight/lenses/<slug>/LENS.MD` | -| `agents.ai_lensers` | `.lenserfight/lensers/<slug>/LENSER.MD` | -| `lenses.workflows` | `.lenserfight/colenses/<slug>/COLENS.MD` | -| `battles.battles` | `.lenserfight/battles/<slug>/BATTLE.MD` | -| `content.tags` | `.lenserfight/rays/<slug>/RAY.MD` | +| `lenses.lenses` | `.lenserfight/lenses/<slug>/SKILL.md` | +| `agents.ai_lensers` | `.lenserfight/lensers/<slug>/SKILL.md` | +| `lenses.workflows` | `.lenserfight/colenses/<slug>/SKILL.md` | +| `battles.battles` | `.lenserfight/battles/<slug>/SKILL.md` | +| `content.tags` | `.lenserfight/rays/<slug>/SKILL.md` | A pgTAP test (`supabase/tests/31_seed_quality.sql`) enforces this invariant for every seed under `supabase/seeds/4*_*templates.sql`. diff --git a/docs/en/tutorials/agent-walkthroughs/automation-rules.md b/docs/en/tutorials/agent-walkthroughs/automation-rules.md index fa9f8a079..8d223b5d3 100644 --- a/docs/en/tutorials/agent-walkthroughs/automation-rules.md +++ b/docs/en/tutorials/agent-walkthroughs/automation-rules.md @@ -20,9 +20,9 @@ Automation in LenserFight is built from canonical markdown objects. Each object | File | Purpose | |------|---------| -| `LENSER.MD` | Describes an AI Lenser — its model, personality, tool access | +| `SKILL.md` | Describes an AI Lenser — its model, personality, tool access | | `AGENT_TEAM.md` | Describes a team composition and edge configuration | -| `COLENS.MD` | Defines a DAG workflow with nodes, edges, and root inputs | +| `SKILL.md` | Defines a DAG workflow with nodes, edges, and root inputs | | `TOOL.md` | Declares a tool's contract (inputs, outputs, permissions) | | `EVALUATION.md` | Specifies how to evaluate lens or workflow output | | `PRIVATE_BATTLE.md` | Defines a head-to-head evaluation between agents | @@ -40,13 +40,13 @@ The CLI can scaffold canonical templates for any object type: ```bash # Generate templates for a workflow and an agent -lf export workflow --template --out ./COLENS.MD -lf export agent --template --out ./LENSER.MD +lf export workflow --template --out ./SKILL.md +lf export agent --template --out ./SKILL.md lf export tool --template --out ./TOOL.md lf export evaluation --template --out ./EVALUATION.md ``` -Open `COLENS.MD` — it looks like this: +Open `SKILL.md` — it looks like this: ```markdown # My Workflow @@ -79,7 +79,7 @@ Before importing, validate all objects in your directory: ```bash # Validate a single file -lf validate ./COLENS.MD +lf validate ./SKILL.md # Validate everything in the current directory lf validate . @@ -119,7 +119,7 @@ lf export workflow <workflow-id> --out ./WORKFLOW-exported.md ```bash # Simulate a workflow and emit a run report -lf workflow run ./COLENS.MD +lf workflow run ./SKILL.md ``` This runs the workflow through the local execution engine and writes a `RUN_REPORT.md` artifact to the current directory. The report includes: @@ -130,7 +130,7 @@ This runs the workflow through the local execution engine and writes a `RUN_REPO To stream output in real time: ```bash -lf workflow run ./COLENS.MD --stream +lf workflow run ./SKILL.md --stream ``` --- @@ -251,8 +251,8 @@ Combining all steps, the recommended local development cycle is: ```bash # 1. Scaffold -lf export agent --template --out ./LENSER.MD -lf export workflow --template --out ./COLENS.MD +lf export agent --template --out ./SKILL.md +lf export workflow --template --out ./SKILL.md # 2. Edit the files to match your automation logic @@ -263,7 +263,7 @@ lf validate . lf import . # 5. Run locally -lf workflow run ./COLENS.MD +lf workflow run ./SKILL.md # 6. Inspect the report cat RUN_REPORT.md diff --git a/docs/en/tutorials/cli/file-based-cli-basics.md b/docs/en/tutorials/cli/file-based-cli-basics.md index d312ef1e7..6b60da24b 100644 --- a/docs/en/tutorials/cli/file-based-cli-basics.md +++ b/docs/en/tutorials/cli/file-based-cli-basics.md @@ -7,19 +7,19 @@ description: First lens, agent, workflow, battle, and ray tutorials for .lenserf ## Create your first Lens -Goal: create `.lenserfight/lenses/customer-summary/LENS.MD`. +Goal: create `.lenserfight/lenses/customer-summary/SKILL.md`. When to use it: you need a reusable prompt transformation. Structure: ```text -.lenserfight/lenses/customer-summary/LENS.MD +.lenserfight/lenses/customer-summary/SKILL.md ``` Item relationship: workflows can reference it with `lens: customer-summary`. -Validation: run `lf validate .lenserfight/lenses/customer-summary/LENS.MD`. +Validation: run `lf validate .lenserfight/lenses/customer-summary/SKILL.md`. Common mistakes: missing frontmatter, vague output contract, placeholders without declared parameters. @@ -27,14 +27,14 @@ Expected outcome: a reusable lens visible in project discovery. ## Create your first Agent -Goal: create `.lenserfight/lensers/researcher/LENSER.MD`. +Goal: create `.lenserfight/lensers/researcher/SKILL.md`. When to use it: you need a reusable AI role with operating rules. Structure: ```text -.lenserfight/lensers/researcher/LENSER.MD +.lenserfight/lensers/researcher/SKILL.md ``` Item relationship: workflows can reference it with `agent: researcher`. @@ -47,14 +47,14 @@ Expected outcome: a role that can be combined with lenses. ## Create your first Workflow -Goal: compose a lens and agent into `.lenserfight/colenses/research-brief/COLENS.MD`. +Goal: compose a lens and agent into `.lenserfight/colenses/research-brief/SKILL.md`. When to use it: the same multi-step process happens repeatedly. Structure: ```text -.lenserfight/colenses/research-brief/COLENS.MD +.lenserfight/colenses/research-brief/SKILL.md ``` Item relationship: `nodes` should reference discovered lens and agent slugs. @@ -74,7 +74,7 @@ When to use it: the team needs evidence for a choice. Structure: ```text -.lenserfight/battles/review-comparison/BATTLE.MD +.lenserfight/battles/review-comparison/SKILL.md ``` Item relationship: participants reference lenses, agents, or workflows. @@ -87,11 +87,11 @@ Expected outcome: a meaningful comparison with explicit criteria. ## Create a Ray -Goal: create `.lenserfight/rays/support/RAY.MD`. +Goal: create `.lenserfight/rays/support/SKILL.md`. When to use it: templates need a shared category. -Validation: `lf validate` parses `RAY.MD` as a first-class item. +Validation: `lf validate` parses `SKILL.md` as a first-class item. Common mistakes: using rays as vague hashtags instead of routeable categories. diff --git a/docs/en/tutorials/cli/file-based-cli-global-and-monorepo.md b/docs/en/tutorials/cli/file-based-cli-global-and-monorepo.md index 08b0e3a89..ffd602d4b 100644 --- a/docs/en/tutorials/cli/file-based-cli-global-and-monorepo.md +++ b/docs/en/tutorials/cli/file-based-cli-global-and-monorepo.md @@ -13,7 +13,7 @@ Structure: ```text ~/.lenserfight/lenserfight.json -~/.lenserfight/lenses/private-brief/LENS.MD +~/.lenserfight/lenses/private-brief/SKILL.md ``` Relationship: project templates can use the same item types; project slugs override global slugs. @@ -31,8 +31,8 @@ Goal: replace `~/.lenserfight/lenses/pr-summary` for one repo. Structure: ```text -~/.lenserfight/lenses/pr-summary/LENS.MD -./.lenserfight/lenses/pr-summary/LENS.MD +~/.lenserfight/lenses/pr-summary/SKILL.md +./.lenserfight/lenses/pr-summary/SKILL.md ``` Relationship: both infer `lens:pr-summary`; the project item wins. @@ -50,8 +50,8 @@ Goal: group templates under `developer`, `finance`, `legal`, or custom rays. Structure: ```text -.lenserfight/rays/developer/RAY.MD -.lenserfight/lenses/code-reviewer/LENS.MD +.lenserfight/rays/developer/SKILL.md +.lenserfight/lenses/code-reviewer/SKILL.md ``` Relationship: templates use `rays: [developer]`. @@ -88,6 +88,6 @@ Goal: explain why a template did or did not load. Validation: run `lf validate --json`. -Common mistakes: filename is not one of `LENS.MD`, `LENSER.MD`, `COLENS.MD`, `BATTLE.MD`, or `RAY.MD`; frontmatter lacks a stable `name` or `slug`. +Common mistakes: filename is not one of `SKILL.md`, `SKILL.md`, `SKILL.md`, `SKILL.md`, or `SKILL.md`; frontmatter lacks a stable `name` or `slug`. Expected outcome: the JSON output lists roots, objects, winners, and conflicts. diff --git a/docs/en/tutorials/cli/file-based-cli-legal-finance-startup.md b/docs/en/tutorials/cli/file-based-cli-legal-finance-startup.md index 012d26775..b04c862ae 100644 --- a/docs/en/tutorials/cli/file-based-cli-legal-finance-startup.md +++ b/docs/en/tutorials/cli/file-based-cli-legal-finance-startup.md @@ -12,7 +12,7 @@ Goal: summarize a document, create a risk checklist, and prepare questions for c Structure: ```text -.lenserfight/colenses/legal-document-review/COLENS.MD +.lenserfight/colenses/legal-document-review/SKILL.md ``` Relationship: legal lenses feed the `legal-triage` agent. @@ -30,7 +30,7 @@ Goal: explain a finance report, review KPIs, and draft an investor update. Structure: ```text -.lenserfight/colenses/finance-report-review/COLENS.MD +.lenserfight/colenses/finance-report-review/SKILL.md ``` Relationship: finance lenses feed the `finance-analyst` agent. @@ -48,7 +48,7 @@ Goal: convert weekly notes into decisions, KPI review, and next actions. Structure: ```text -.lenserfight/colenses/startup-weekly-operating-review/COLENS.MD +.lenserfight/colenses/startup-weekly-operating-review/SKILL.md ``` Relationship: founder review, KPI review, and decision memo lenses feed the startup operator agent. diff --git a/docs/en/tutorials/cli/file-based-cli-pr-and-content-workflows.md b/docs/en/tutorials/cli/file-based-cli-pr-and-content-workflows.md index 4185b075d..ea675c3f2 100644 --- a/docs/en/tutorials/cli/file-based-cli-pr-and-content-workflows.md +++ b/docs/en/tutorials/cli/file-based-cli-pr-and-content-workflows.md @@ -12,15 +12,15 @@ Goal: produce triage, code review, test plan, and PR description. Structure: ```text -.lenserfight/lenses/code-reviewer/LENS.MD -.lenserfight/lenses/unit-test-generator/LENS.MD -.lenserfight/lenses/pr-description-writer/LENS.MD -.lenserfight/colenses/pr-review/COLENS.MD +.lenserfight/lenses/code-reviewer/SKILL.md +.lenserfight/lenses/unit-test-generator/SKILL.md +.lenserfight/lenses/pr-description-writer/SKILL.md +.lenserfight/colenses/pr-review/SKILL.md ``` Relationship: the workflow intentionally chains specialized lenses. -Validation: `lf validate .lenserfight/colenses/pr-review/COLENS.MD` for syntax, `lf validate` for cross-references. +Validation: `lf validate .lenserfight/colenses/pr-review/SKILL.md` for syntax, `lf validate` for cross-references. Common mistakes: reviewing without diff context, generating tests unrelated to changed behavior. @@ -33,7 +33,7 @@ Goal: create script, storyboard, thumbnail prompt, and short-form repurposing. Structure: ```text -.lenserfight/colenses/youtube-content/COLENS.MD +.lenserfight/colenses/youtube-content/SKILL.md ``` Relationship: a content producer agent reviews the outputs from creator lenses. diff --git a/docs/en/tutorials/developer-examples/research-to-rubric-colens.md b/docs/en/tutorials/developer-examples/research-to-rubric-colens.md index ed2956bf5..3a18fbbad 100644 --- a/docs/en/tutorials/developer-examples/research-to-rubric-colens.md +++ b/docs/en/tutorials/developer-examples/research-to-rubric-colens.md @@ -7,7 +7,7 @@ description: Simulate a multi-step file-first colens that prepares battle tasks ## Purpose -Learn how LenserFight represents a Colens as a local `COLENS.MD` automation object with ordered steps, lenser references, a Lens reference, and approval gates. +Learn how LenserFight represents a Colens as a local `SKILL.md` automation object with ordered steps, lenser references, a Lens reference, and approval gates. ## Concepts Covered @@ -15,7 +15,7 @@ Colens, Lens reference, AI lenser, AI lenser team, approval gate, evaluation out ## What You Will Build -You will simulate [`examples/colenses/research-to-rubric`](../../../examples/colenses/research-to-rubric/README.md), a colens that turns a topic into a battle task and rubric. +You will simulate [`examples/colenses/research-to-rubric`](../../../../examples/colenses/research-to-rubric/README.md), a colens that turns a topic into a battle task and rubric. ## Prerequisites @@ -27,13 +27,13 @@ You will simulate [`examples/colenses/research-to-rubric`](../../../examples/col ```text examples/colenses/research-to-rubric/ - COLENS.MD + SKILL.md README.md ``` ## Step-by-Step Walkthrough -1. Open `COLENS.MD`. +1. Open `SKILL.md`. 2. Inspect `colens_type: evaluation`. 3. Review the four steps: `lens_execution`, two `agent_task` steps, and an `approval_gate`. 4. Pass a topic through `--inputs`. @@ -43,7 +43,7 @@ examples/colenses/research-to-rubric/ ```bash pnpm nx run cli:build -node dist/apps/cli/main.js colens run examples/colenses/research-to-rubric/COLENS.MD --inputs '{"topic":"local battle scoring"}' +node dist/apps/cli/main.js colens run examples/colenses/research-to-rubric/SKILL.md --inputs '{"topic":"local battle scoring"}' ``` ## Expected Output @@ -74,4 +74,4 @@ The CLI validates the automation object, reads `frontmatter.steps`, summarizes e ## Example Folder -[`examples/colenses/research-to-rubric`](../../../examples/colenses/research-to-rubric/README.md) +[`examples/colenses/research-to-rubric`](../../../../examples/colenses/research-to-rubric/README.md) diff --git a/docs/en/tutorials/developer-examples/review-lenser-team.md b/docs/en/tutorials/developer-examples/review-lenser-team.md index 5bf56b9ab..425b35550 100644 --- a/docs/en/tutorials/developer-examples/review-lenser-team.md +++ b/docs/en/tutorials/developer-examples/review-lenser-team.md @@ -15,7 +15,7 @@ AI lenser, AI lenser team, team lead, shared tools, colens ownership, execution ## What You Will Build -You will validate [`examples/lensers/review-lenser-team`](../../../examples/lensers/review-lenser-team/README.md), a researcher lenser, reviewer lenser, and team definition. +You will validate [`examples/lensers/review-lenser-team`](../../../../examples/lensers/review-lenser-team/README.md), a researcher lenser, reviewer lenser, and team definition. ## Prerequisites @@ -28,17 +28,17 @@ You will validate [`examples/lensers/review-lenser-team`](../../../examples/lens ```text examples/lensers/review-lenser-team/ researcher/ - LENSER.MD + SKILL.md reviewer/ - LENSER.MD + SKILL.md TEAM.MD README.md ``` ## Step-by-Step Walkthrough -1. Open `researcher/LENSER.MD` and inspect `role`, `capabilities`, `model_policy`, and `allowed_actions`. -2. Open `reviewer/LENSER.MD` and compare its responsibilities. +1. Open `researcher/SKILL.md` and inspect `role`, `capabilities`, `model_policy`, and `allowed_actions`. +2. Open `reviewer/SKILL.md` and compare its responsibilities. 3. Open `TEAM.MD` and inspect `members`, `team_lead_lenser`, and `colens_ownership`. 4. Validate the folder. @@ -71,4 +71,4 @@ Agent objects carry instructions and execution policy. The team object does not ## Example Folder -[`examples/lensers/review-lenser-team`](../../../examples/lensers/review-lenser-team/README.md) +[`examples/lensers/review-lenser-team`](../../../../examples/lensers/review-lenser-team/README.md) diff --git a/docs/en/tutorials/file-based-cli-basics.md b/docs/en/tutorials/file-based-cli-basics.md index d312ef1e7..6b60da24b 100644 --- a/docs/en/tutorials/file-based-cli-basics.md +++ b/docs/en/tutorials/file-based-cli-basics.md @@ -7,19 +7,19 @@ description: First lens, agent, workflow, battle, and ray tutorials for .lenserf ## Create your first Lens -Goal: create `.lenserfight/lenses/customer-summary/LENS.MD`. +Goal: create `.lenserfight/lenses/customer-summary/SKILL.md`. When to use it: you need a reusable prompt transformation. Structure: ```text -.lenserfight/lenses/customer-summary/LENS.MD +.lenserfight/lenses/customer-summary/SKILL.md ``` Item relationship: workflows can reference it with `lens: customer-summary`. -Validation: run `lf validate .lenserfight/lenses/customer-summary/LENS.MD`. +Validation: run `lf validate .lenserfight/lenses/customer-summary/SKILL.md`. Common mistakes: missing frontmatter, vague output contract, placeholders without declared parameters. @@ -27,14 +27,14 @@ Expected outcome: a reusable lens visible in project discovery. ## Create your first Agent -Goal: create `.lenserfight/lensers/researcher/LENSER.MD`. +Goal: create `.lenserfight/lensers/researcher/SKILL.md`. When to use it: you need a reusable AI role with operating rules. Structure: ```text -.lenserfight/lensers/researcher/LENSER.MD +.lenserfight/lensers/researcher/SKILL.md ``` Item relationship: workflows can reference it with `agent: researcher`. @@ -47,14 +47,14 @@ Expected outcome: a role that can be combined with lenses. ## Create your first Workflow -Goal: compose a lens and agent into `.lenserfight/colenses/research-brief/COLENS.MD`. +Goal: compose a lens and agent into `.lenserfight/colenses/research-brief/SKILL.md`. When to use it: the same multi-step process happens repeatedly. Structure: ```text -.lenserfight/colenses/research-brief/COLENS.MD +.lenserfight/colenses/research-brief/SKILL.md ``` Item relationship: `nodes` should reference discovered lens and agent slugs. @@ -74,7 +74,7 @@ When to use it: the team needs evidence for a choice. Structure: ```text -.lenserfight/battles/review-comparison/BATTLE.MD +.lenserfight/battles/review-comparison/SKILL.md ``` Item relationship: participants reference lenses, agents, or workflows. @@ -87,11 +87,11 @@ Expected outcome: a meaningful comparison with explicit criteria. ## Create a Ray -Goal: create `.lenserfight/rays/support/RAY.MD`. +Goal: create `.lenserfight/rays/support/SKILL.md`. When to use it: templates need a shared category. -Validation: `lf validate` parses `RAY.MD` as a first-class item. +Validation: `lf validate` parses `SKILL.md` as a first-class item. Common mistakes: using rays as vague hashtags instead of routeable categories. diff --git a/docs/en/tutorials/file-based-cli-global-and-monorepo.md b/docs/en/tutorials/file-based-cli-global-and-monorepo.md index 08b0e3a89..ffd602d4b 100644 --- a/docs/en/tutorials/file-based-cli-global-and-monorepo.md +++ b/docs/en/tutorials/file-based-cli-global-and-monorepo.md @@ -13,7 +13,7 @@ Structure: ```text ~/.lenserfight/lenserfight.json -~/.lenserfight/lenses/private-brief/LENS.MD +~/.lenserfight/lenses/private-brief/SKILL.md ``` Relationship: project templates can use the same item types; project slugs override global slugs. @@ -31,8 +31,8 @@ Goal: replace `~/.lenserfight/lenses/pr-summary` for one repo. Structure: ```text -~/.lenserfight/lenses/pr-summary/LENS.MD -./.lenserfight/lenses/pr-summary/LENS.MD +~/.lenserfight/lenses/pr-summary/SKILL.md +./.lenserfight/lenses/pr-summary/SKILL.md ``` Relationship: both infer `lens:pr-summary`; the project item wins. @@ -50,8 +50,8 @@ Goal: group templates under `developer`, `finance`, `legal`, or custom rays. Structure: ```text -.lenserfight/rays/developer/RAY.MD -.lenserfight/lenses/code-reviewer/LENS.MD +.lenserfight/rays/developer/SKILL.md +.lenserfight/lenses/code-reviewer/SKILL.md ``` Relationship: templates use `rays: [developer]`. @@ -88,6 +88,6 @@ Goal: explain why a template did or did not load. Validation: run `lf validate --json`. -Common mistakes: filename is not one of `LENS.MD`, `LENSER.MD`, `COLENS.MD`, `BATTLE.MD`, or `RAY.MD`; frontmatter lacks a stable `name` or `slug`. +Common mistakes: filename is not one of `SKILL.md`, `SKILL.md`, `SKILL.md`, `SKILL.md`, or `SKILL.md`; frontmatter lacks a stable `name` or `slug`. Expected outcome: the JSON output lists roots, objects, winners, and conflicts. diff --git a/docs/en/tutorials/file-based-cli-legal-finance-startup.md b/docs/en/tutorials/file-based-cli-legal-finance-startup.md index 012d26775..b04c862ae 100644 --- a/docs/en/tutorials/file-based-cli-legal-finance-startup.md +++ b/docs/en/tutorials/file-based-cli-legal-finance-startup.md @@ -12,7 +12,7 @@ Goal: summarize a document, create a risk checklist, and prepare questions for c Structure: ```text -.lenserfight/colenses/legal-document-review/COLENS.MD +.lenserfight/colenses/legal-document-review/SKILL.md ``` Relationship: legal lenses feed the `legal-triage` agent. @@ -30,7 +30,7 @@ Goal: explain a finance report, review KPIs, and draft an investor update. Structure: ```text -.lenserfight/colenses/finance-report-review/COLENS.MD +.lenserfight/colenses/finance-report-review/SKILL.md ``` Relationship: finance lenses feed the `finance-analyst` agent. @@ -48,7 +48,7 @@ Goal: convert weekly notes into decisions, KPI review, and next actions. Structure: ```text -.lenserfight/colenses/startup-weekly-operating-review/COLENS.MD +.lenserfight/colenses/startup-weekly-operating-review/SKILL.md ``` Relationship: founder review, KPI review, and decision memo lenses feed the startup operator agent. diff --git a/docs/en/tutorials/file-based-cli-pr-and-content-workflows.md b/docs/en/tutorials/file-based-cli-pr-and-content-workflows.md index 4185b075d..ea675c3f2 100644 --- a/docs/en/tutorials/file-based-cli-pr-and-content-workflows.md +++ b/docs/en/tutorials/file-based-cli-pr-and-content-workflows.md @@ -12,15 +12,15 @@ Goal: produce triage, code review, test plan, and PR description. Structure: ```text -.lenserfight/lenses/code-reviewer/LENS.MD -.lenserfight/lenses/unit-test-generator/LENS.MD -.lenserfight/lenses/pr-description-writer/LENS.MD -.lenserfight/colenses/pr-review/COLENS.MD +.lenserfight/lenses/code-reviewer/SKILL.md +.lenserfight/lenses/unit-test-generator/SKILL.md +.lenserfight/lenses/pr-description-writer/SKILL.md +.lenserfight/colenses/pr-review/SKILL.md ``` Relationship: the workflow intentionally chains specialized lenses. -Validation: `lf validate .lenserfight/colenses/pr-review/COLENS.MD` for syntax, `lf validate` for cross-references. +Validation: `lf validate .lenserfight/colenses/pr-review/SKILL.md` for syntax, `lf validate` for cross-references. Common mistakes: reviewing without diff context, generating tests unrelated to changed behavior. @@ -33,7 +33,7 @@ Goal: create script, storyboard, thumbnail prompt, and short-form repurposing. Structure: ```text -.lenserfight/colenses/youtube-content/COLENS.MD +.lenserfight/colenses/youtube-content/SKILL.md ``` Relationship: a content producer agent reviews the outputs from creator lenses. diff --git a/docs/en/tutorials/walkthroughs/create-a-lens.md b/docs/en/tutorials/walkthroughs/create-a-lens.md index b63696d77..206757647 100644 --- a/docs/en/tutorials/walkthroughs/create-a-lens.md +++ b/docs/en/tutorials/walkthroughs/create-a-lens.md @@ -82,8 +82,8 @@ Once published, your lens can be selected in the workflow builder or referenced For developers who prefer terminal-driven workflows or want to manage Lenses as code, use the `lf` CLI. - **[CLI: Create a Lens](/en/tutorials/cli/cli-getting-started#step-5-create-your-first-lens)** — Step-by-step Lens creation via terminal -- **[CLI: Create a Workflow](/en/tutorials/cli/file-based-cli-basics#create-your-first-workflow)** — Compose Lenses into multi-step processes via `COLENS.MD` -- **[CLI: Create a Battle](/en/tutorials/cli/file-based-cli-basics#create-your-first-battle)** — Compare Lens outputs from the terminal via `BATTLE.MD` +- **[CLI: Create a Workflow](/en/tutorials/cli/file-based-cli-basics#create-your-first-workflow)** — Compose Lenses into multi-step processes via `SKILL.md` +- **[CLI: Create a Battle](/en/tutorials/cli/file-based-cli-basics#create-your-first-battle)** — Compare Lens outputs from the terminal via `SKILL.md` See the [CLI: Getting Started](/en/tutorials/cli/cli-getting-started) guide for installation and authentication. diff --git a/libs/data/repositories/src/lib/repositories/lensesRepository.ts b/libs/data/repositories/src/lib/repositories/lensesRepository.ts index 18f9ce401..e3b3330a7 100644 --- a/libs/data/repositories/src/lib/repositories/lensesRepository.ts +++ b/libs/data/repositories/src/lib/repositories/lensesRepository.ts @@ -251,11 +251,12 @@ export class SupabaseLensesRepository implements LensesRepositoryPort { ownerId?: string | null ): Promise<ApiResponseEnvelope<LensRecord[]>> { const start = Date.now() - const { data, error } = await supabase + let publicQuery = supabase .from('vw_lenses_public') .select(this.listLensSelect) .ilike('title', `%${query}%`) - .range(offset, offset + limit - 1) + if (ownerId) publicQuery = publicQuery.eq('lenser_id', ownerId) + const { data, error } = await publicQuery.range(offset, offset + limit - 1) if (error) this.handleError(error) const publicResults = (data ?? []) as unknown as LensRecord[] diff --git a/libs/domain/spec-governance/src/lib/spec-kinds.spec.ts b/libs/domain/spec-governance/src/lib/spec-kinds.spec.ts index 0c50c90df..5794e57d4 100644 --- a/libs/domain/spec-governance/src/lib/spec-kinds.spec.ts +++ b/libs/domain/spec-governance/src/lib/spec-kinds.spec.ts @@ -90,7 +90,7 @@ describe('getSpecKindMeta', () => { it('returns the correct meta for Lens', () => { const meta = getSpecKindMeta('Lens') expect(meta.kind).toBe('Lens') - expect(meta.fileName).toBe('LENS.MD') + expect(meta.fileName).toBe('SKILL.md') expect(meta.legacyKind).toBe('lens') }) }) diff --git a/libs/domain/spec-governance/src/lib/spec-kinds.ts b/libs/domain/spec-governance/src/lib/spec-kinds.ts index aef2b7e45..30e8d8c02 100644 --- a/libs/domain/spec-governance/src/lib/spec-kinds.ts +++ b/libs/domain/spec-governance/src/lib/spec-kinds.ts @@ -115,7 +115,7 @@ export const SPEC_KIND_META: Record<SpecKind, SpecKindMeta> = { Lens: { kind: 'Lens', legacyKind: 'lens', - fileName: 'LENS.MD', + fileName: 'SKILL.md', description: 'A reusable, versioned prompt contract with typed inputs and outputs. The fundamental executable unit of LenserFight.', requiredFields: ['kind', 'name', 'description'], @@ -127,7 +127,7 @@ export const SPEC_KIND_META: Record<SpecKind, SpecKindMeta> = { Lenser: { kind: 'Lenser', legacyKind: 'lenser', - fileName: 'LENSER.MD', + fileName: 'SKILL.md', description: 'An AI agent with a defined mission, tool policy, and operating rules. Runs lenses and coordinates with other lensers.', requiredFields: ['kind', 'name', 'description'], @@ -139,7 +139,7 @@ export const SPEC_KIND_META: Record<SpecKind, SpecKindMeta> = { CoLens: { kind: 'CoLens', legacyKind: 'colens', - fileName: 'COLENS.MD', + fileName: 'SKILL.md', description: 'A multi-step workflow DAG that chains lenses and lensers. Supports sequential, parallel, and conditional execution.', requiredFields: ['kind', 'name', 'description'], @@ -151,7 +151,7 @@ export const SPEC_KIND_META: Record<SpecKind, SpecKindMeta> = { Battle: { kind: 'Battle', legacyKind: 'battle', - fileName: 'BATTLE.MD', + fileName: 'SKILL.md', description: 'A public comparison template between lenses, lensers, workflows, or models. Supports AI-vs-AI, human-vs-human, and human-vs-AI structures.', requiredFields: ['kind', 'name', 'description'], @@ -163,7 +163,7 @@ export const SPEC_KIND_META: Record<SpecKind, SpecKindMeta> = { Ray: { kind: 'Ray', legacyKind: 'ray', - fileName: 'RAY.MD', + fileName: 'SKILL.md', description: 'A thematic category that groups related lenses, lensers, colenses, and battles for discovery.', requiredFields: ['kind', 'name', 'description'], diff --git a/libs/features/exports/src/lib/components/ExportButton.tsx b/libs/features/exports/src/lib/components/ExportButton.tsx index 511edf880..94fe2237f 100644 --- a/libs/features/exports/src/lib/components/ExportButton.tsx +++ b/libs/features/exports/src/lib/components/ExportButton.tsx @@ -1,17 +1,10 @@ -import React, { useCallback, useState } from 'react' +import React, { useState } from 'react' import { Download } from 'lucide-react' import { Button } from '@lenserfight/ui/components' -import type { ExportContext, ExportFormat, ExportKind } from '@lenserfight/domain/exports' -import { supabase } from '@lenserfight/data/supabase' -import { SupabaseExportsRepository } from '@lenserfight/data/exports' -import { useAuth } from '@lenserfight/features/auth' +import type { ExportKind } from '@lenserfight/domain/exports' -import { CloudDownloadTransport } from '../transport/CloudDownloadTransport' -import { LocalDownloadTransport } from '../transport/LocalDownloadTransport' -import type { TransportId } from '../transport/ExportTransport' -import { useExportRunner } from '../hooks/useExportRunner' import { ExportModal } from './ExportModal' export interface ExportButtonProps<T> { @@ -48,35 +41,6 @@ export function ExportButton<T>({ isOwner = false, }: ExportButtonProps<T>) { const [open, setOpen] = useState(false) - const { user, isAuthenticated } = useAuth() - - const buildContext = useCallback((): ExportContext => ({ - userId: user?.id ?? null, - tenantId: null, - via: 'web', - host: typeof window !== 'undefined' ? window.location.host : '', - isOwner, - isAuthenticated, - }), [user?.id, isOwner, isAuthenticated]) - - const resolveTransport = useCallback((id: TransportId) => { - if (id === 'local-download') return new LocalDownloadTransport() - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return new CloudDownloadTransport(new SupabaseExportsRepository(supabase as any)) - }, []) - - const runExportInner = useExportRunner<T>({ - kind, - slug, - title, - fetchPayload, - buildContext, - resolveTransport, - }) - const runExport = useCallback( - async (input: { format: ExportFormat; destination: TransportId }) => { await runExportInner(input) }, - [runExportInner], - ) return ( <> @@ -99,7 +63,7 @@ export function ExportButton<T>({ slug={slug} title={title} fetchPayload={fetchPayload} - onConfirm={runExport} + isOwner={isOwner} /> </> ) diff --git a/libs/features/lenses/src/lib/components/LabExecutionPanel.tsx b/libs/features/lenses/src/lib/components/LabExecutionPanel.tsx index 063744e4b..6cec30e66 100644 --- a/libs/features/lenses/src/lib/components/LabExecutionPanel.tsx +++ b/libs/features/lenses/src/lib/components/LabExecutionPanel.tsx @@ -85,6 +85,8 @@ interface LabExecutionPanelProps { profileId?: string /** Called with the current param values when the user clicks "Save preset". Not rendered if omitted. */ onSavePreset?: (values: Record<string, unknown>) => void + /** Called with the current param values and params after a successful "Copy with Parameters". */ + onCopyWithParams?: (values: Record<string, unknown>, params: LensVersionParam[]) => void /** When set, triggers applyImportedValues on the internal param form to bulk-apply preset values. */ importedPresetValues?: Record<string, unknown> | null // Funding source @@ -169,6 +171,7 @@ export const LabExecutionPanel: React.FC<LabExecutionPanelProps> = ({ profileId, onSavePreset, importedPresetValues, + onCopyWithParams, }) => { const form = useLabParamForm(lensContent, params, versionParams) @@ -298,7 +301,6 @@ export const LabExecutionPanel: React.FC<LabExecutionPanelProps> = ({ const [jsonImportOpen, setJsonImportOpen] = useState(false) const [csvImportOpen, setCsvImportOpen] = useState(false) const [copiedWithParams, setCopiedWithParams] = useState(false) - const [copiedWithInternalIds, setCopiedWithInternalIds] = useState(false) const isNonEmpty = (v: unknown) => { if (v === undefined || v === null) return false @@ -330,17 +332,7 @@ export const LabExecutionPanel: React.FC<LabExecutionPanelProps> = ({ } catch { // clipboard failed — leave state unchanged } - } - - const handleCopyWithInternalIds = async () => { - try { - const rendered = await renderCopyWithParameters(false) - await copyTextToClipboard(rendered) - setCopiedWithInternalIds(true) - setTimeout(() => setCopiedWithInternalIds(false), 2000) - } catch { - // clipboard failed — leave state unchanged - } + onCopyWithParams?.(form.inputValues, form.effectiveParams) } const isDisabled = @@ -937,26 +929,6 @@ export const LabExecutionPanel: React.FC<LabExecutionPanelProps> = ({ </> )} </Button> - <Button - type="button" - variant="ghost" - onClick={handleCopyWithInternalIds} - disabled={isLocked} - title="Copy with media_object_id UUIDs for LenserFight execution (internal)" - className={`flex-shrink-0 flex items-center justify-center gap-2 h-auto py-2 px-3 rounded-xl border shadow-sm transition-all text-xs ${copiedWithInternalIds - ? 'bg-slate-600 border-slate-600 text-white' - : 'bg-slate-50 border-slate-200 text-slate-700 hover:bg-slate-100 dark:bg-slate-900/30 dark:border-slate-700 dark:text-slate-200' - }`} - > - {copiedWithInternalIds ? ( - <> - <Check size={14} strokeWidth={3} /> - <span>Copied IDs</span> - </> - ) : ( - <span>Internal IDs</span> - )} - </Button> </> )} </div> diff --git a/libs/features/lenses/src/lib/hooks/useLensesFeed.ts b/libs/features/lenses/src/lib/hooks/useLensesFeed.ts index cad3e6026..8f83c9286 100644 --- a/libs/features/lenses/src/lib/hooks/useLensesFeed.ts +++ b/libs/features/lenses/src/lib/hooks/useLensesFeed.ts @@ -6,12 +6,16 @@ import { lensesService } from '@lenserfight/data/repositories' export const useLensesFeed = ( searchQuery: string, selectedTag: string | null, - sortOrder: 'newest' | 'popular' | 'mine' + sortOrder: 'newest' | 'popular' | 'mine', + profileId?: string | null ) => { return useInfiniteQuery({ - queryKey: queryKeys.lenses.feed({ searchQuery, selectedTag, sortOrder }), + queryKey: queryKeys.lenses.feed({ searchQuery, selectedTag, sortOrder, profileId }), queryFn: async ({ pageParam = 0 }) => { - if (sortOrder === 'mine') return lensesService.getMyLenses(pageParam, 12) + if (sortOrder === 'mine') { + if (searchQuery) return lensesService.search(searchQuery, pageParam, 12, profileId) + return lensesService.getMyLenses(pageParam, 12) + } if (searchQuery) return lensesService.search(searchQuery, pageParam, 12) if (selectedTag) return lensesService.filter(selectedTag, pageParam, 12, sortOrder) return lensesService.sort(sortOrder, pageParam, 12) diff --git a/libs/features/lenses/src/lib/pages/LensDetailPage.tsx b/libs/features/lenses/src/lib/pages/LensDetailPage.tsx index 3bfa0bd04..2642ca889 100644 --- a/libs/features/lenses/src/lib/pages/LensDetailPage.tsx +++ b/libs/features/lenses/src/lib/pages/LensDetailPage.tsx @@ -6,15 +6,8 @@ import { useReportContent } from '@lenserfight/features/feedback' import { useShareContext } from '@lenserfight/features/share' import { useChainabitConnection } from '@lenserfight/features/store' import { CreateVersionParamInput, ReportReasonEnum } from '@lenserfight/types' -import { - ExportModal, - useExportRunner, - LocalDownloadTransport, - CloudDownloadTransport, -} from '@lenserfight/features/exports' +import { ExportModal } from '@lenserfight/features/exports' import type { LensExportPayload } from '@lenserfight/shared/serializers' -import { SupabaseExportsRepository } from '@lenserfight/data/exports' -import { supabase } from '@lenserfight/data/supabase' import { SEOHead, Badge, Button, Card, DesktopFrame, HelpButton } from '@lenserfight/ui/components' import { ArtifactLifecycleMenu, @@ -204,45 +197,6 @@ export const LensDetailPage: React.FC = () => { isEditMode, } = useCreateLens() - const buildExportContext = useCallback( - () => ({ - userId: user?.id ?? null, - tenantId: null, - via: 'web' as const, - host: window.location.host, - isOwner, - isAuthenticated, - }), - [user?.id, isOwner, isAuthenticated] - ) - - const resolveExportTransport = useCallback( - (id: 'cloud-download' | 'local-download' | 'local-workspace') => { - if (id === 'local-download') return new LocalDownloadTransport() - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return new CloudDownloadTransport(new SupabaseExportsRepository(supabase as any)) - }, - [] - ) - - const runExportInner = useExportRunner({ - kind: 'lens', - slug: lens?.id ?? '', - title: lens?.title ?? null, - fetchPayload: async () => lens, - buildContext: buildExportContext, - resolveTransport: resolveExportTransport, - }) - const runExport = useCallback( - async (input: { - format: import('@lenserfight/domain/exports').ExportFormat - destination: import('@lenserfight/features/exports').TransportId - }) => { - await runExportInner(input) - }, - [runExportInner] - ) - const ensureProfile = useCallback((): boolean => { if (!isAuthenticated) { redirectToLogin() @@ -555,7 +509,7 @@ export const LensDetailPage: React.FC = () => { options: p.tool.options ?? null, })), })} - onConfirm={runExport} + isOwner={isOwner} /> } /> diff --git a/libs/features/lenses/src/lib/pages/LensLabPage.tsx b/libs/features/lenses/src/lib/pages/LensLabPage.tsx index e4bb55b82..ab03d53b2 100644 --- a/libs/features/lenses/src/lib/pages/LensLabPage.tsx +++ b/libs/features/lenses/src/lib/pages/LensLabPage.tsx @@ -1,20 +1,13 @@ import { queryKeys } from '@lenserfight/data/cache' import { lensesService, preferencesService } from '@lenserfight/data/repositories' import type { LensVersion } from '@lenserfight/types' -import { - ExportModal, - useExportRunner, - LocalDownloadTransport, - CloudDownloadTransport, -} from '@lenserfight/features/exports' +import { ExportModal } from '@lenserfight/features/exports' import type { LensExportPayload } from '@lenserfight/shared/serializers' -import { SupabaseExportsRepository } from '@lenserfight/data/exports' -import { supabase } from '@lenserfight/data/supabase' import { useAuth } from '@lenserfight/features/auth' import { useReportContent } from '@lenserfight/features/feedback' import { useShareContext } from '@lenserfight/features/share' import { useChainabitConnection } from '@lenserfight/features/store' -import { LenserPreferences } from '@lenserfight/types' +import { LenserPreferences, LensVersionParam } from '@lenserfight/types' import { ReportReasonEnum } from '@lenserfight/types' import { Button, HelpButton, SEOHead } from '@lenserfight/ui/components' import { ConfirmModal } from '@lenserfight/ui/modals' @@ -23,7 +16,7 @@ import { useUI } from '@lenserfight/ui/providers' import { useDrawerRouter } from '@lenserfight/ui/routing' import { copyTextToClipboard, renderLensContentForCopy } from '@lenserfight/utils/text' import { useQuery, useQueryClient } from '@tanstack/react-query' -import { History, Lock, Loader2, Pencil, Trash2, Flag, ListVideo } from 'lucide-react' +import { History, Lock, Loader2, Pencil, Trash2, Flag, ListVideo, Upload } from 'lucide-react' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useParams, useNavigate } from 'react-router-dom' @@ -140,10 +133,17 @@ export const LensLabPage: React.FC = () => { // Version list — lazy until picker opens (URL route resolves main without full list) const [showVersionPicker, setShowVersionPicker] = useState(false) - const { versions, isLoading: isLoadingVersions } = useLensVersions(id ?? '', { + const { versions, isLoading: isLoadingVersions, publishVersion } = useLensVersions(id ?? '', { enabled: showVersionPicker, }) + const handlePublishVersion = useCallback(async () => { + const versionId = lens?.latestPublishedVersion?.id ?? lens?.headVersionId + if (!versionId) return + await publishVersion(versionId) + queryClient.invalidateQueries({ queryKey: ['lens-core', id] }) + }, [lens?.latestPublishedVersion?.id, lens?.headVersionId, publishVersion, queryClient, id]) + const displayVersion = versionRoute.activeVersion const activeLensContent = displayVersion?.templateBody ?? '' const activeVersionParams = displayVersion?.parameters @@ -172,6 +172,19 @@ export const LensLabPage: React.FC = () => { const [isDeleting, setIsDeleting] = useState(false) const [deleteTargetId, setDeleteTargetId] = useState<string | null>(null) + type ParamSnapshot = { values: Record<string, unknown>; params: LensVersionParam[]; at: number } + const [paramSnapshots, setParamSnapshots] = useState<ParamSnapshot[]>([]) + const [appliedSnapshotValues, setAppliedSnapshotValues] = useState<Record<string, unknown> | null>(null) + + const handleCopyWithParams = useCallback( + (values: Record<string, unknown>, params: LensVersionParam[]) => { + const hasValues = Object.values(values).some((v) => v !== '' && v != null) + if (!hasValues) return + setParamSnapshots((prev) => [{ values, params, at: Date.now() }, ...prev].slice(0, 10)) + }, + [] + ) + const { isOpen: isCreateOpen, openModal: openCreateModal, @@ -197,45 +210,6 @@ export const LensLabPage: React.FC = () => { const isOwner = !!(lenser && lens && lens.author.id === lenser.id) - const buildExportContext = useCallback( - () => ({ - userId: user?.id ?? null, - tenantId: null, - via: 'web' as const, - host: window.location.host, - isOwner, - isAuthenticated, - }), - [user?.id, isOwner, isAuthenticated] - ) - - const resolveExportTransport = useCallback( - (id: 'cloud-download' | 'local-download' | 'local-workspace') => { - if (id === 'local-download') return new LocalDownloadTransport() - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return new CloudDownloadTransport(new SupabaseExportsRepository(supabase as any)) - }, - [] - ) - - const runExportInner = useExportRunner({ - kind: 'lens', - slug: lens?.id ?? '', - title: lens?.title ?? null, - fetchPayload: async () => lens, - buildContext: buildExportContext, - resolveTransport: resolveExportTransport, - }) - const runExport = useCallback( - async (input: { - format: import('@lenserfight/domain/exports').ExportFormat - destination: import('@lenserfight/features/exports').TransportId - }) => { - await runExportInner(input) - }, - [runExportInner] - ) - const handleDeleteClick = useCallback((targetId: string) => { setDeleteTargetId(targetId) setIsDeleteModalOpen(true) @@ -252,12 +226,18 @@ export const LensLabPage: React.FC = () => { if (editId && lenser) { lensesService.getLensDetail(editId, lenser.id).then((detail) => { if (detail) { + const params = (detail.latestPublishedVersion?.parameters ?? []) as LensVersionParam[] openCreateModal({ id: detail.id, title: detail.title, - content: detail.content, + content: renderLensContentForCopy(detail.content, params), tags: detail.tags, visibility: detail.visibility, + versionParams: params.map((p) => ({ + label: p.label, + toolId: p.toolId, + ...(p.optional ? { optional: true } : {}), + })), }) } }) @@ -270,7 +250,7 @@ export const LensLabPage: React.FC = () => { if (!lens?.id) return [] if (isOwner) { - return [ + const actions: { label: string; icon: React.ReactNode; onClick: () => void; variant?: 'danger' }[] = [ { label: 'Edit Lens', icon: <Pencil size={16} />, @@ -280,9 +260,19 @@ export const LensLabPage: React.FC = () => { label: 'Delete Lens', icon: <Trash2 size={16} />, onClick: () => handleDeleteClick(lens.id), - variant: 'danger' as const, + variant: 'danger', }, ] + + if (lens.latestPublishedVersion?.status === 'draft') { + actions.unshift({ + label: 'Publish', + icon: <Upload size={16} />, + onClick: handlePublishVersion, + }) + } + + return actions } if (hasActiveLenserProfile) { @@ -297,7 +287,7 @@ export const LensLabPage: React.FC = () => { } return [] - }, [handleDeleteClick, handleEditClick, hasActiveLenserProfile, isOwner, lens?.id]) + }, [handleDeleteClick, handleEditClick, handlePublishVersion, hasActiveLenserProfile, isOwner, lens?.id, lens?.latestPublishedVersion?.status]) useEffect(() => { setPageActions(pageActions) @@ -454,7 +444,7 @@ export const LensLabPage: React.FC = () => { options: p.tool.options ?? null, })), })} - onConfirm={runExport} + isOwner={isOwner} /> } /> @@ -491,8 +481,8 @@ export const LensLabPage: React.FC = () => { onClick={() => setShowVersionPicker((v) => !v)} title={showVersionPicker ? 'Hide version history' : 'Show version history'} className={`flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-lg border shadow-sm transition-all ${showVersionPicker - ? 'border-primary-200 dark:border-primary-800 bg-primary-50 dark:bg-primary-900/20 text-primary-600 dark:text-primary-400' - : 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:border-gray-300 dark:hover:border-gray-600' + ? 'border-primary-200 dark:border-primary-800 bg-primary-50 dark:bg-primary-900/20 text-primary-600 dark:text-primary-400' + : 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:border-gray-300 dark:hover:border-gray-600' }`} > <History size={13} /> @@ -543,8 +533,8 @@ export const LensLabPage: React.FC = () => { ) } className={`w-full text-left px-4 py-2.5 flex items-center gap-3 transition-colors ${isSelected - ? 'bg-primary-50 dark:bg-primary-900/20 text-primary-700 dark:text-primary-300' - : 'hover:bg-gray-50 dark:hover:bg-gray-800/60 text-gray-700 dark:text-gray-300' + ? 'bg-primary-50 dark:bg-primary-900/20 text-primary-700 dark:text-primary-300' + : 'hover:bg-gray-50 dark:hover:bg-gray-800/60 text-gray-700 dark:text-gray-300' }`} > <span className="font-mono font-bold text-xs w-8 shrink-0"> @@ -552,8 +542,8 @@ export const LensLabPage: React.FC = () => { </span> <span className={`text-[10px] px-1.5 py-0.5 rounded-full font-medium shrink-0 ${v.status === 'draft' - ? 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300' - : 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300' + ? 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300' + : 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300' }`} > {v.status} @@ -655,6 +645,8 @@ export const LensLabPage: React.FC = () => { onSignIn={ensureProfile} lensTitle={lens?.title ?? undefined} profileId={lenser?.id ?? undefined} + onCopyWithParams={handleCopyWithParams} + importedPresetValues={appliedSnapshotValues} /> </div> </div> @@ -663,60 +655,74 @@ export const LensLabPage: React.FC = () => { <div className="grid grid-cols-1 lg:grid-cols-12 gap-6 mt-2"> {/* Execution timeline — right 5 cols (offset to align with execution panel) */} <div className="lg:col-start-8 lg:col-span-5 border-t pt-6 border-gray-100 dark:border-gray-800 lg:border-t-0 lg:pt-0 flex flex-col gap-6"> - {activeVersionParams && activeVersionParams.length > 0 && ( + {paramSnapshots.length > 0 && ( <div> <h4 className="text-sm font-semibold text-gray-800 dark:text-gray-100 mb-3"> - Parameters + Copied parameter sets </h4> - <div className="space-y-2"> - {activeVersionParams.map((p) => ( + <div className="space-y-3"> + {paramSnapshots.map((snap) => ( <div - key={p.id} - className="flex items-start gap-3 rounded-lg border border-gray-100 dark:border-gray-800 bg-gray-50 dark:bg-gray-900/50 px-3 py-2 text-xs" + key={snap.at} + className="rounded-lg border border-gray-100 dark:border-gray-800 bg-gray-50 dark:bg-gray-900/50 px-3 py-2 text-xs" > - <code className="font-mono text-primary-600 dark:text-primary-400 shrink-0"> - [[{p.label}]] - </code> - <span className="text-gray-500 dark:text-gray-400 shrink-0">{p.tool.type}</span> - {p.tool.helpText && ( - <span className="text-gray-400 dark:text-gray-500 truncate">{p.tool.helpText}</span> - )} - {p.optional && ( - <span className="ml-auto shrink-0 text-gray-400 dark:text-gray-600 italic">optional</span> - )} + <div className="space-y-1 mb-2"> + {snap.params.map((p) => { + const val = snap.values[p.label] + if (val === '' || val == null) return null + return ( + <div key={p.label} className="flex gap-2"> + <code className="font-mono text-primary-600 dark:text-primary-400 shrink-0"> + {p.label} + </code> + <span className="text-gray-700 dark:text-gray-300 truncate">{String(val)}</span> + </div> + ) + })} + </div> + <button + type="button" + className="text-xs font-medium text-primary-600 dark:text-primary-400 hover:underline" + onClick={() => { + setAppliedSnapshotValues({ ...snap.values }) + setTimeout(() => setAppliedSnapshotValues(null), 0) + }} + > + Reuse + </button> </div> ))} </div> </div> )} <div> - <div className="flex items-center gap-2 mb-4"> - <h4 className="text-sm font-semibold text-gray-800 dark:text-gray-100">History</h4> - {lab.comparisonRunIds.length > 0 && ( - <span className="text-xs text-primary-600 dark:text-primary-400 font-medium"> - {lab.comparisonRunIds.length}/2 selected - </span> - )} - </div> - <LabExecutionTimeline - history={lab.history} - isLoading={lab.isLoadingHistory} - hasMore={lab.hasMoreHistory} - selectedRunId={lab.selectedRunId} - comparisonRunIds={lab.comparisonRunIds} - onSelectRun={(_requestId, runId) => runId && lab.setSelectedRunId(runId)} - onToggleComparison={lab.toggleComparison} - onLoadMore={lab.loadMoreHistory} - isOwner={isOwner} - onRestoreVersion={(versionId) => { - versionExecution.restoreAndExecute(versionId) - const cached = queryClient.getQueryData<LensVersion>( - queryKeys.lensVersions.detail(versionId) - ) - if (cached && id) versionRoute.navigateToVersion(cached.versionNumber) - }} - isAuthenticatedLenser={hasActiveLenserProfile} - /> + <div className="flex items-center gap-2 mb-4"> + <h4 className="text-sm font-semibold text-gray-800 dark:text-gray-100">History</h4> + {lab.comparisonRunIds.length > 0 && ( + <span className="text-xs text-primary-600 dark:text-primary-400 font-medium"> + {lab.comparisonRunIds.length}/2 selected + </span> + )} + </div> + <LabExecutionTimeline + history={lab.history} + isLoading={lab.isLoadingHistory} + hasMore={lab.hasMoreHistory} + selectedRunId={lab.selectedRunId} + comparisonRunIds={lab.comparisonRunIds} + onSelectRun={(_requestId, runId) => runId && lab.setSelectedRunId(runId)} + onToggleComparison={lab.toggleComparison} + onLoadMore={lab.loadMoreHistory} + isOwner={isOwner} + onRestoreVersion={(versionId) => { + versionExecution.restoreAndExecute(versionId) + const cached = queryClient.getQueryData<LensVersion>( + queryKeys.lensVersions.detail(versionId) + ) + if (cached && id) versionRoute.navigateToVersion(cached.versionNumber) + }} + isAuthenticatedLenser={hasActiveLenserProfile} + /> </div> </div> </div> diff --git a/libs/features/lenses/src/lib/pages/LensesPage.tsx b/libs/features/lenses/src/lib/pages/LensesPage.tsx index 481f072df..0658cef31 100644 --- a/libs/features/lenses/src/lib/pages/LensesPage.tsx +++ b/libs/features/lenses/src/lib/pages/LensesPage.tsx @@ -34,7 +34,14 @@ export const LensesPage: React.FC = () => { // URL-synced filters const selectedTag = searchParams.get('tag') - const sortOrder = (searchParams.get('sort') as LensesSortOrder) || 'popular' + const sortOrder = useMemo<LensesSortOrder>(() => { + const urlSort = searchParams.get('sort') as LensesSortOrder | null + if (urlSort) return urlSort + if (isAuthenticated) { + return (localStorage.getItem('lenses_sort_order') as LensesSortOrder) || 'mine' + } + return 'popular' + }, [searchParams, isAuthenticated]) const searchQuery = searchParams.get('q') ?? '' const outputKindFilter = (searchParams.get('kind') as OutputKindFilter) || 'all' @@ -67,6 +74,7 @@ export const LensesPage: React.FC = () => { } const handleSortChange = (order: LensesSortOrder) => { + localStorage.setItem('lenses_sort_order', order) setSearchParams( (prev) => { if (order !== 'popular') prev.set('sort', order) @@ -92,7 +100,8 @@ export const LensesPage: React.FC = () => { const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = useLensesFeed( searchQuery, selectedTag, - sortOrder + sortOrder, + user?.id ) const lenses = useMemo(() => { diff --git a/libs/features/profile/src/lib/pages/LenserProfilePage.tsx b/libs/features/profile/src/lib/pages/LenserProfilePage.tsx index 50d2be21a..90cd1704b 100644 --- a/libs/features/profile/src/lib/pages/LenserProfilePage.tsx +++ b/libs/features/profile/src/lib/pages/LenserProfilePage.tsx @@ -189,6 +189,7 @@ export const LenserProfilePage: React.FC = () => { }) const [loadingTab, setLoadingTab] = useState(false) const observer = useRef<IntersectionObserver | null>(null) + const isFetchingPageRef = useRef(false) const activeStandardState = activeStandardTab ? tabCache[activeStandardTab] : INITIAL_TAB_STATE const { data: items, page, hasMore } = activeStandardState @@ -218,6 +219,7 @@ export const LenserProfilePage: React.FC = () => { useEffect(() => { if (!handle) return + isFetchingPageRef.current = false setTabCache({ threads: { ...INITIAL_TAB_STATE }, lenses: { ...INITIAL_TAB_STATE }, @@ -250,7 +252,9 @@ export const LenserProfilePage: React.FC = () => { if (!viewedProfile) return if (!authUser) return if (!refresh && tabCache[targetTab].isLoaded && pageNum === 0) return + if (isFetchingPageRef.current) return + isFetchingPageRef.current = true if (pageNum === 0) setLoadingTab(true) try { @@ -309,6 +313,7 @@ export const LenserProfilePage: React.FC = () => { } catch (cause) { console.error(`Failed to fetch ${targetTab}`, cause) } finally { + isFetchingPageRef.current = false setLoadingTab(false) } } @@ -414,8 +419,11 @@ export const LenserProfilePage: React.FC = () => { fetchTabData(tab, 0, true) } - const handlePromptSubmit = () => { + const handlePromptSubmit = (id: string) => { handleMutationSuccess('lenses') + if (isPromptEditMode) { + navigate(`/lenses/${id}/main`) + } } const SkeletonLoader = () => { diff --git a/libs/features/shell/src/lib/Sidebar/humanSidebar.tsx b/libs/features/shell/src/lib/Sidebar/humanSidebar.tsx index 6bdd3e9e8..fced79804 100644 --- a/libs/features/shell/src/lib/Sidebar/humanSidebar.tsx +++ b/libs/features/shell/src/lib/Sidebar/humanSidebar.tsx @@ -7,7 +7,6 @@ import { Home, Hourglass, KeyRound, - LayoutTemplate, Library, MessageCircle, Server, @@ -37,13 +36,6 @@ export function buildHumanSidebarSections( { id: 'overview', label: 'Discover', path: '/', exact: true, icon: <Home size={20} /> }, ], }, - { - id: 'chat', - label: 'Chat', - items: [ - { id: 'chat', label: 'Chat', path: '/chat', exact: true, icon: <MessageCircle size={20} />, wip: true }, - ], - }, { id: 'arena', label: 'Arena', @@ -54,7 +46,6 @@ export function buildHumanSidebarSections( { id: 'battles', label: 'Battles', path: '/battles', icon: <Swords size={20} /> }, { id: 'lensers', label: 'AI Lensers & Agents', path: '/lensers', icon: <Users size={20} /> }, { id: 'lenserboard', label: 'LenserBoard', path: '/lenserboard', icon: <Trophy size={20} /> }, - { id: 'leaderboard', label: 'Leaderboard', path: '/leaderboard', icon: <Trophy size={20} /> }, ], }, { @@ -76,6 +67,13 @@ export function buildHumanSidebarSections( { id: 'gateway-daemons', label: 'Gateway', path: '/settings/gateway', icon: <Server size={20} /> }, ], }, + { + id: 'chat', + label: 'Chat', + items: [ + { id: 'chat', label: 'Chat', path: '/chat', exact: true, icon: <MessageCircle size={20} />, wip: true }, + ], + }, ] return sections.filter((section) => section.items.length > 0) diff --git a/supabase/migrations/20270601000027_fix_lens_version_detail_anon_access.sql b/supabase/migrations/20270601000027_fix_lens_version_detail_anon_access.sql new file mode 100644 index 000000000..d1605c1fd --- /dev/null +++ b/supabase/migrations/20270601000027_fix_lens_version_detail_anon_access.sql @@ -0,0 +1,174 @@ +-- Fix anon access to fn_get_lens_version_detail and fn_get_lens_version_parameters. +-- +-- Root causes: +-- +-- 1. fn_get_lens_version_detail: prior version (migration 024) lacked +-- SET row_security TO off. lenses.versions has FORCE ROW LEVEL SECURITY, +-- which blocks even the postgres superuser when row_security is on inside a +-- SECURITY DEFINER function. Result: empty set for all callers including anon +-- on public lenses. +-- +-- 2. fn_get_lens_version_parameters / fn_get_version_params_with_tools: both +-- lacked SET row_security TO off AND lacked any visibility check. lenses.version_parameters +-- has FORCE RLS with no anon policy → always empty for anon users. Also a security +-- hole: any caller could enumerate parameters for private lenses by supplying a +-- known version UUID. +-- +-- Visibility rules (mirrors fn_get_lens_detail_bootstrap): +-- public → anon + authenticated, published only +-- community → authenticated only, published only +-- followers → accepted followers only, published only +-- private → owner only (any status) + +-- ── fn_get_lens_version_detail ──────────────────────────────────────────────── + +DROP FUNCTION IF EXISTS public.fn_get_lens_version_detail(uuid); + +CREATE FUNCTION public.fn_get_lens_version_detail(p_version_id uuid) +RETURNS TABLE( + id uuid, + lens_id uuid, + version_number integer, + status text, + template_body text, + changelog text, + parent_version_id uuid, + published_at timestamptz, + created_at timestamptz +) +LANGUAGE sql +STABLE +SECURITY DEFINER +SET search_path TO 'public', 'lenses', 'content', 'lensers' +SET row_security TO off +AS $$ + SELECT + v.id, + v.lens_id, + v.version_number, + v.status::text, + v.template_body, + v.changelog, + v.parent_version_id, + v.published_at, + v.created_at + FROM lenses.versions v + JOIN lenses.lenses l ON l.id = v.lens_id + WHERE v.id = p_version_id + AND ( + -- Owner sees their own versions regardless of status or visibility + l.lenser_id = lensers.get_auth_lenser_id() + -- Public lenses: everyone (anon + authenticated), published only + OR ( + l.visibility = 'public'::content.visibility_enum + AND v.status = 'published'::content.content_status + ) + -- Community lenses: authenticated users, published only + OR ( + l.visibility = 'community'::content.visibility_enum + AND v.status = 'published'::content.content_status + AND lensers.get_auth_lenser_id() IS NOT NULL + ) + -- Followers-only lenses: accepted followers, published only + OR ( + l.visibility = 'followers'::content.visibility_enum + AND v.status = 'published'::content.content_status + AND lensers.get_auth_lenser_id() IS NOT NULL + AND lensers.fn_viewer_follows_owner(lensers.get_auth_lenser_id(), l.lenser_id) + ) + ); +$$; + +ALTER FUNCTION public.fn_get_lens_version_detail(uuid) OWNER TO postgres; +GRANT EXECUTE ON FUNCTION public.fn_get_lens_version_detail(uuid) TO anon, authenticated, service_role; + +-- ── fn_get_version_params_with_tools ───────────────────────────────────────── +-- Visibility-gated helper. Callers (fn_get_lens_version_parameters) rely on this. + +DROP FUNCTION IF EXISTS lenses.fn_get_version_params_with_tools(uuid); + +CREATE FUNCTION lenses.fn_get_version_params_with_tools(p_version_id uuid) +RETURNS jsonb +LANGUAGE sql +STABLE +SECURITY DEFINER +SET search_path TO 'lenses', 'content', 'lensers', 'public' +SET row_security TO off +AS $$ + SELECT COALESCE( + jsonb_agg( + jsonb_build_object( + 'id', vp.id, + 'version_id', vp.version_id, + 'label', vp.label, + 'tool_id', vp.tool_id, + 'optional', COALESCE(vp.optional, false), + 'tool', jsonb_build_object( + 'id', t.id, + 'key', t.key, + 'label', t.label, + 'description', t.description, + 'category', t.category, + 'type', t.type, + 'required', t.required, + 'min_length', t.min_length, + 'max_length', t.max_length, + 'placeholder', t.placeholder, + 'help_text', t.help_text, + 'validation_schema', t.validation_schema, + 'options', COALESCE(vp.options, t.options), + 'sort_order', t.sort_order, + 'is_system', t.is_system, + 'icon', t.icon, + 'color', t.color + ) + ) + ORDER BY t.sort_order, vp.label + ), + '[]'::jsonb + ) + FROM lenses.version_parameters vp + JOIN lenses.tools t ON t.id = vp.tool_id + JOIN lenses.versions v ON v.id = vp.version_id + JOIN lenses.lenses l ON l.id = v.lens_id + WHERE vp.version_id = p_version_id + AND ( + l.lenser_id = lensers.get_auth_lenser_id() + OR ( + l.visibility = 'public'::content.visibility_enum + AND v.status = 'published'::content.content_status + ) + OR ( + l.visibility = 'community'::content.visibility_enum + AND v.status = 'published'::content.content_status + AND lensers.get_auth_lenser_id() IS NOT NULL + ) + OR ( + l.visibility = 'followers'::content.visibility_enum + AND v.status = 'published'::content.content_status + AND lensers.get_auth_lenser_id() IS NOT NULL + AND lensers.fn_viewer_follows_owner(lensers.get_auth_lenser_id(), l.lenser_id) + ) + ); +$$; + +ALTER FUNCTION lenses.fn_get_version_params_with_tools(uuid) OWNER TO postgres; +GRANT EXECUTE ON FUNCTION lenses.fn_get_version_params_with_tools(uuid) TO anon, authenticated, service_role; + +-- ── fn_get_lens_version_parameters (public wrapper) ────────────────────────── + +DROP FUNCTION IF EXISTS public.fn_get_lens_version_parameters(uuid); + +CREATE FUNCTION public.fn_get_lens_version_parameters(p_version_id uuid) +RETURNS jsonb +LANGUAGE sql +STABLE +SECURITY DEFINER +SET search_path TO 'public', 'lenses', 'lensers' +SET row_security TO off +AS $$ + SELECT lenses.fn_get_version_params_with_tools(p_version_id); +$$; + +ALTER FUNCTION public.fn_get_lens_version_parameters(uuid) OWNER TO postgres; +GRANT EXECUTE ON FUNCTION public.fn_get_lens_version_parameters(uuid) TO anon, authenticated, service_role; diff --git a/supabase/migrations/20270601000028_publish_initial_lens_version.sql b/supabase/migrations/20270601000028_publish_initial_lens_version.sql new file mode 100644 index 000000000..b5a67a254 --- /dev/null +++ b/supabase/migrations/20270601000028_publish_initial_lens_version.sql @@ -0,0 +1,164 @@ +-- Fix: public/community lenses should have their initial version published immediately. +-- +-- Root cause: +-- fn_create_lens (migration 019) calls fn_create_draft_version, which always inserts +-- a lenses.versions row with status = 'draft'. The lens row itself is created with +-- status = 'published', but every RPC that serves non-owners (fn_get_lens_detail_bootstrap, +-- fn_get_lens_version_detail, fn_get_lens_version_parameters) gates access on +-- v.status = 'published'. Result: a brand-new public lens always has +-- latest_published_version = null for anonymous/non-owner viewers. +-- +-- Fix: +-- 1. Update fn_create_lens to publish the initial version automatically for any +-- visibility != 'private'. +-- 2. Backfill existing public/community lenses whose head version is still a draft +-- (no published version exists for them at all). + +-- ── 1. fn_create_lens: auto-publish initial version for non-private lenses ─── + +DROP FUNCTION IF EXISTS lenses.fn_create_lens( + content.visibility_enum, text, text, text, text, jsonb, uuid[], uuid, uuid +); + +CREATE OR REPLACE FUNCTION lenses.fn_create_lens( + p_visibility content.visibility_enum, + p_template_body text, + p_title text, + p_description text DEFAULT NULL, + p_language_code text DEFAULT 'en', + p_params jsonb DEFAULT '[]'::jsonb, + p_tag_ids uuid[] DEFAULT '{}'::uuid[], + p_parent_lens_id uuid DEFAULT NULL, + p_forked_from_execution_id uuid DEFAULT NULL +) RETURNS uuid + LANGUAGE plpgsql SECURITY DEFINER + SET search_path TO 'lenses', 'content', 'lensers', 'public' + AS $$ +DECLARE + v_caller_id uuid; + v_new_lens_id uuid; + v_new_version lenses.versions; + v_tag_id uuid; + v_param jsonb; + v_param_id uuid; + v_text_tool uuid; + v_uuid_body text; +BEGIN + v_caller_id := lensers.get_auth_lenser_id(); + IF v_caller_id IS NULL THEN + RAISE EXCEPTION 'Not authenticated' USING ERRCODE = 'insufficient_privilege'; + END IF; + + IF length(trim(p_template_body)) < 50 THEN + RAISE EXCEPTION 'template_body must be at least 50 characters (got %)', + length(trim(p_template_body)) USING ERRCODE = 'check_violation'; + END IF; + + INSERT INTO lenses.lenses ( + lenser_id, visibility, status, + parent_lens_id, forked_from_execution_id + ) VALUES ( + v_caller_id, p_visibility, 'published'::content.content_status, + p_parent_lens_id, p_forked_from_execution_id + ) RETURNING id INTO v_new_lens_id; + + v_new_version := lenses.fn_create_draft_version( + v_new_lens_id, p_template_body, 'Initial version' + ); + + -- Immediately publish the initial version for non-private lenses so that + -- anonymous and non-owner viewers can access the content right away. + IF p_visibility != 'private'::content.visibility_enum THEN + UPDATE lenses.versions + SET status = 'published'::content.content_status, published_at = now() + WHERE id = v_new_version.id; + END IF; + + UPDATE lenses.lenses SET head_version_id = v_new_version.id WHERE id = v_new_lens_id; + + v_uuid_body := p_template_body; + + IF p_params IS NOT NULL AND jsonb_array_length(p_params) > 0 THEN + SELECT id INTO v_text_tool FROM lenses.tools WHERE key = 'text' LIMIT 1; + + FOR v_param IN SELECT * FROM jsonb_array_elements(p_params) LOOP + INSERT INTO lenses.version_parameters (version_id, label, tool_id, optional, options) + VALUES ( + v_new_version.id, + v_param->>'label', + COALESCE(NULLIF(v_param->>'tool_id', '')::uuid, v_text_tool), + COALESCE((v_param->>'optional')::boolean, false), + CASE + WHEN v_param->'options' IS NOT NULL + AND jsonb_typeof(v_param->'options') = 'array' + THEN v_param->'options' + ELSE NULL + END + ) + RETURNING id INTO v_param_id; + + v_uuid_body := lenses.fn_replace_param_label_token( + v_uuid_body, + v_param->>'label', + '[[:' || v_param_id::text || ']]' + ); + END LOOP; + + UPDATE lenses.versions SET template_body = v_uuid_body WHERE id = v_new_version.id; + END IF; + + INSERT INTO content.entity_translations ( + entity_type, entity_id, language_code, is_original, + title, description, content + ) VALUES ( + 'lens'::content.entity_type_enum, v_new_lens_id, + COALESCE(p_language_code, 'en'), true, + p_title, p_description, p_template_body + ); + + IF p_tag_ids IS NOT NULL AND array_length(p_tag_ids, 1) > 0 THEN + FOREACH v_tag_id IN ARRAY p_tag_ids LOOP + INSERT INTO content.tag_map (entity_type, entity_id, tag_id) + VALUES ('lens'::content.entity_type_enum, v_new_lens_id, v_tag_id) + ON CONFLICT DO NOTHING; + END LOOP; + END IF; + + RETURN v_new_lens_id; +END; +$$; + +ALTER FUNCTION lenses.fn_create_lens( + content.visibility_enum, text, text, text, text, jsonb, uuid[], uuid, uuid +) OWNER TO postgres; + +GRANT EXECUTE ON FUNCTION lenses.fn_create_lens( + content.visibility_enum, text, text, text, text, jsonb, uuid[], uuid, uuid +) TO authenticated, service_role; + +-- ── 2. Backfill: publish head version for existing public/community lenses ─── +-- +-- Targets lenses where: +-- - visibility is public or community +-- - no published version exists +-- - head_version_id points to a draft version +-- +-- Safe to run multiple times (WHERE v.status = 'draft' guard prevents double-publish). + +UPDATE lenses.versions v +SET + status = 'published'::content.content_status, + published_at = COALESCE(v.created_at, now()) +FROM lenses.lenses l +WHERE l.head_version_id = v.id + AND l.visibility IN ( + 'public'::content.visibility_enum, + 'community'::content.visibility_enum + ) + AND v.status = 'draft'::content.content_status + AND NOT EXISTS ( + SELECT 1 + FROM lenses.versions pv + WHERE pv.lens_id = l.id + AND pv.status = 'published'::content.content_status + ); diff --git a/supabase/migrations/20270601000029_fix_create_lens_publish_order.sql b/supabase/migrations/20270601000029_fix_create_lens_publish_order.sql new file mode 100644 index 000000000..60cf424dd --- /dev/null +++ b/supabase/migrations/20270601000029_fix_create_lens_publish_order.sql @@ -0,0 +1,135 @@ +-- Fix: creating a non-private lens with parameters fails with +-- "Published versions are immutable (id=...). Create a new draft instead." (23514) +-- +-- Root cause (migration 028): +-- fn_create_lens published the initial version (status -> 'published') BEFORE the +-- parameter loop rewrote template_body with UUID tokens. The trigger +-- lenses.fn_prevent_published_version_update blocks any UPDATE on a published row, +-- so the subsequent `UPDATE lenses.versions SET template_body = ...` raised 23514. +-- Lenses without parameters skipped that UPDATE, so the bug only surfaced when the +-- template contained [[tokens]]. +-- +-- Fix: +-- Publish the initial version LAST — after head_version_id is set, parameters are +-- inserted, and template_body is rewritten. The version stays a draft for every +-- mutation, then flips to published as the final step for non-private lenses. + +DROP FUNCTION IF EXISTS lenses.fn_create_lens( + content.visibility_enum, text, text, text, text, jsonb, uuid[], uuid, uuid +); + +CREATE OR REPLACE FUNCTION lenses.fn_create_lens( + p_visibility content.visibility_enum, + p_template_body text, + p_title text, + p_description text DEFAULT NULL, + p_language_code text DEFAULT 'en', + p_params jsonb DEFAULT '[]'::jsonb, + p_tag_ids uuid[] DEFAULT '{}'::uuid[], + p_parent_lens_id uuid DEFAULT NULL, + p_forked_from_execution_id uuid DEFAULT NULL +) RETURNS uuid + LANGUAGE plpgsql SECURITY DEFINER + SET search_path TO 'lenses', 'content', 'lensers', 'public' + AS $$ +DECLARE + v_caller_id uuid; + v_new_lens_id uuid; + v_new_version lenses.versions; + v_tag_id uuid; + v_param jsonb; + v_param_id uuid; + v_text_tool uuid; + v_uuid_body text; +BEGIN + v_caller_id := lensers.get_auth_lenser_id(); + IF v_caller_id IS NULL THEN + RAISE EXCEPTION 'Not authenticated' USING ERRCODE = 'insufficient_privilege'; + END IF; + + IF length(trim(p_template_body)) < 50 THEN + RAISE EXCEPTION 'template_body must be at least 50 characters (got %)', + length(trim(p_template_body)) USING ERRCODE = 'check_violation'; + END IF; + + INSERT INTO lenses.lenses ( + lenser_id, visibility, status, + parent_lens_id, forked_from_execution_id + ) VALUES ( + v_caller_id, p_visibility, 'published'::content.content_status, + p_parent_lens_id, p_forked_from_execution_id + ) RETURNING id INTO v_new_lens_id; + + v_new_version := lenses.fn_create_draft_version( + v_new_lens_id, p_template_body, 'Initial version' + ); + + UPDATE lenses.lenses SET head_version_id = v_new_version.id WHERE id = v_new_lens_id; + + v_uuid_body := p_template_body; + + IF p_params IS NOT NULL AND jsonb_array_length(p_params) > 0 THEN + SELECT id INTO v_text_tool FROM lenses.tools WHERE key = 'text' LIMIT 1; + + FOR v_param IN SELECT * FROM jsonb_array_elements(p_params) LOOP + INSERT INTO lenses.version_parameters (version_id, label, tool_id, optional, options) + VALUES ( + v_new_version.id, + v_param->>'label', + COALESCE(NULLIF(v_param->>'tool_id', '')::uuid, v_text_tool), + COALESCE((v_param->>'optional')::boolean, false), + CASE + WHEN v_param->'options' IS NOT NULL + AND jsonb_typeof(v_param->'options') = 'array' + THEN v_param->'options' + ELSE NULL + END + ) + RETURNING id INTO v_param_id; + + v_uuid_body := lenses.fn_replace_param_label_token( + v_uuid_body, + v_param->>'label', + '[[:' || v_param_id::text || ']]' + ); + END LOOP; + + UPDATE lenses.versions SET template_body = v_uuid_body WHERE id = v_new_version.id; + END IF; + + INSERT INTO content.entity_translations ( + entity_type, entity_id, language_code, is_original, + title, description, content + ) VALUES ( + 'lens'::content.entity_type_enum, v_new_lens_id, + COALESCE(p_language_code, 'en'), true, + p_title, p_description, p_template_body + ); + + IF p_tag_ids IS NOT NULL AND array_length(p_tag_ids, 1) > 0 THEN + FOREACH v_tag_id IN ARRAY p_tag_ids LOOP + INSERT INTO content.tag_map (entity_type, entity_id, tag_id) + VALUES ('lens'::content.entity_type_enum, v_new_lens_id, v_tag_id) + ON CONFLICT DO NOTHING; + END LOOP; + END IF; + + -- Publish the initial version LAST, after all mutations to the version row, + -- so the immutability trigger never sees an UPDATE on a published row. + IF p_visibility != 'private'::content.visibility_enum THEN + UPDATE lenses.versions + SET status = 'published'::content.content_status, published_at = now() + WHERE id = v_new_version.id; + END IF; + + RETURN v_new_lens_id; +END; +$$; + +ALTER FUNCTION lenses.fn_create_lens( + content.visibility_enum, text, text, text, text, jsonb, uuid[], uuid, uuid +) OWNER TO postgres; + +GRANT EXECUTE ON FUNCTION lenses.fn_create_lens( + content.visibility_enum, text, text, text, text, jsonb, uuid[], uuid, uuid +) TO authenticated, service_role;