feat(skills): foundation + web-search pilot + market-monitor template (#543)#552
Open
clemenshelm wants to merge 2 commits into
Open
feat(skills): foundation + web-search pilot + market-monitor template (#543)#552clemenshelm wants to merge 2 commits into
clemenshelm wants to merge 2 commits into
Conversation
11 tasks
clemenshelm
pushed a commit
that referenced
this pull request
Jun 18, 2026
Addressing the independent code-review pass on #552: * Soft-deleted agents no longer get SKILL.md materialized into their stale workspaces. The pre-existing config-emission pattern still builds entries for `deletedAt` agents (broader to untangle), but the new skill-write step short-circuits on them so the workspaces don't accumulate dead files. * `getSkillBody()` now memoizes the SKILL.md body in a process-local cache. With 50 agents on the same skill, this drops the regenerate from 50 redundant disk reads to one. First-party skill bodies are bundled with the build and never change at runtime, so the cache has no invalidation semantics to worry about. * Skill materialization moved out of the `agentsList.map(...)` callback into a dedicated post-pass — `.map` shouldn't have side effects, and the second pass is the natural place for the `deletedAt` guard. * `assertValidSkillId` tightened to `/^[a-z][a-z0-9-]*$/` so digit-first ids ("99-bottles") and uppercase ids ("WebSearch") are rejected. The digit case was accepted previously even though it breaks the AgentSkills.io convention this layer follows. Two new test cases. * Drift guard broadened: `agent-templates-web.test.ts` now iterates every `AGENT_TEMPLATES` entry and asserts that any `defaultSkills` member is in `KNOWN_SKILLS`. Catches a template-skill mismatch at test time rather than at the runtime guard in `regenerateOpenClawConfig` (which only fires when a user instantiates the template). * `?? []` defense-in-depth on `agent.skills` documented inline — the column is `notNull().default('[]')`, so the null path is unreachable post-migration; the fallback is there to keep an in-flight regenerate race quiet rather than throwing an opaque TypeError. * Self-contradicting comment in `web-agents.ts` removed ("No allowedTools listed here" sat above `allowedTools: [...]`). * `web-search` SKILL.md: Safety section moved ahead of Output format so the model attends to it earlier in the prompt. * Doc examples in `create-market-monitor-agent.mdx` rephrased to be evergreen ("this quarter", "in our industry") instead of bound to specific 2026 events.
4 tasks
clemenshelm
pushed a commit
that referenced
this pull request
Jun 19, 2026
Addressing the independent code-review pass on #552: * Soft-deleted agents no longer get SKILL.md materialized into their stale workspaces. The pre-existing config-emission pattern still builds entries for `deletedAt` agents (broader to untangle), but the new skill-write step short-circuits on them so the workspaces don't accumulate dead files. * `getSkillBody()` now memoizes the SKILL.md body in a process-local cache. With 50 agents on the same skill, this drops the regenerate from 50 redundant disk reads to one. First-party skill bodies are bundled with the build and never change at runtime, so the cache has no invalidation semantics to worry about. * Skill materialization moved out of the `agentsList.map(...)` callback into a dedicated post-pass — `.map` shouldn't have side effects, and the second pass is the natural place for the `deletedAt` guard. * `assertValidSkillId` tightened to `/^[a-z][a-z0-9-]*$/` so digit-first ids ("99-bottles") and uppercase ids ("WebSearch") are rejected. The digit case was accepted previously even though it breaks the AgentSkills.io convention this layer follows. Two new test cases. * Drift guard broadened: `agent-templates-web.test.ts` now iterates every `AGENT_TEMPLATES` entry and asserts that any `defaultSkills` member is in `KNOWN_SKILLS`. Catches a template-skill mismatch at test time rather than at the runtime guard in `regenerateOpenClawConfig` (which only fires when a user instantiates the template). * `?? []` defense-in-depth on `agent.skills` documented inline — the column is `notNull().default('[]')`, so the null path is unreachable post-migration; the fallback is there to keep an in-flight regenerate race quiet rather than throwing an opaque TypeError. * Self-contradicting comment in `web-agents.ts` removed ("No allowedTools listed here" sat above `allowedTools: [...]`). * `web-search` SKILL.md: Safety section moved ahead of Output format so the model attends to it earlier in the prompt. * Doc examples in `create-market-monitor-agent.mdx` rephrased to be evergreen ("this quarter", "in our industry") instead of bound to specific 2026 events.
3b3ee65 to
2ef0662
Compare
clemenshelm
pushed a commit
that referenced
this pull request
Jun 19, 2026
Addressing the independent code-review pass on #552: * Soft-deleted agents no longer get SKILL.md materialized into their stale workspaces. The pre-existing config-emission pattern still builds entries for `deletedAt` agents (broader to untangle), but the new skill-write step short-circuits on them so the workspaces don't accumulate dead files. * `getSkillBody()` now memoizes the SKILL.md body in a process-local cache. With 50 agents on the same skill, this drops the regenerate from 50 redundant disk reads to one. First-party skill bodies are bundled with the build and never change at runtime, so the cache has no invalidation semantics to worry about. * Skill materialization moved out of the `agentsList.map(...)` callback into a dedicated post-pass — `.map` shouldn't have side effects, and the second pass is the natural place for the `deletedAt` guard. * `assertValidSkillId` tightened to `/^[a-z][a-z0-9-]*$/` so digit-first ids ("99-bottles") and uppercase ids ("WebSearch") are rejected. The digit case was accepted previously even though it breaks the AgentSkills.io convention this layer follows. Two new test cases. * Drift guard broadened: `agent-templates-web.test.ts` now iterates every `AGENT_TEMPLATES` entry and asserts that any `defaultSkills` member is in `KNOWN_SKILLS`. Catches a template-skill mismatch at test time rather than at the runtime guard in `regenerateOpenClawConfig` (which only fires when a user instantiates the template). * `?? []` defense-in-depth on `agent.skills` documented inline — the column is `notNull().default('[]')`, so the null path is unreachable post-migration; the fallback is there to keep an in-flight regenerate race quiet rather than throwing an opaque TypeError. * Self-contradicting comment in `web-agents.ts` removed ("No allowedTools listed here" sat above `allowedTools: [...]`). * `web-search` SKILL.md: Safety section moved ahead of Output format so the model attends to it earlier in the prompt. * Doc examples in `create-market-monitor-agent.mdx` rephrased to be evergreen ("this quarter", "in our industry") instead of bound to specific 2026 events.
added 2 commits
June 19, 2026 09:30
…#543) Adopts OpenClaw 2026.6.x's native skill mechanics — SKILL.md, six-tier loading precedence, per-agent `agents.list[].skills` allowlist — as Pinchy's composition unit for agent capabilities. v1 reference impl per master tracking issue #543. * Add `agents.skills jsonb` column with a Drizzle migration. Empty default; existing rows untouched. * New `KNOWN_SKILLS` const with drift-guard test enforcing on-disk truth (workspace `<id>/SKILL.md` ↔ list). * New first-party skill `web-search` with workflow guidelines for `pinchy_web_search` / `pinchy_web_fetch` (source-grounded, recency- aware, no-fabrication invariants). * `writeWorkspaceSkill` materializes SKILL.md to `<workspace>/skills/<id>/SKILL.md` so OC's workspace-tier loader picks it up. * `regenerateOpenClawConfig` emits `agents.list[].skills` for every agent — always, even empty. Verified in Docker smoke-test against OC 2026.6.5: `skills: []` excludes all 58 bundled OC desktop skills (1password, apple-notes, ...) that are irrelevant for enterprise agents. * `AgentTemplate.defaultSkills?: string[]` added additively. Existing 33 templates unchanged; new agents inherit the template's allowlist at create. * Pilot template `market-monitor` ("Market & News Monitor") in the marketing-web category, pinchy-web plugin, defaultSkills: ["web-search"]. Persona-only AGENTS.md; workflow lives in the skill. * `requiresWeb` access badge + permission preview for `pinchy-web` templates; templates API + new-agent-form propagate the flag. * Audit hook snapshots `skills` in `agent.created` detail. * Docs: `guides/create-market-monitor-agent.mdx`. Closes #354 #126 #372 (consolidated into master #543). Phase 1 migration sub-issues #544 #545 #546.
Addressing the independent code-review pass on #552: * Soft-deleted agents no longer get SKILL.md materialized into their stale workspaces. The pre-existing config-emission pattern still builds entries for `deletedAt` agents (broader to untangle), but the new skill-write step short-circuits on them so the workspaces don't accumulate dead files. * `getSkillBody()` now memoizes the SKILL.md body in a process-local cache. With 50 agents on the same skill, this drops the regenerate from 50 redundant disk reads to one. First-party skill bodies are bundled with the build and never change at runtime, so the cache has no invalidation semantics to worry about. * Skill materialization moved out of the `agentsList.map(...)` callback into a dedicated post-pass — `.map` shouldn't have side effects, and the second pass is the natural place for the `deletedAt` guard. * `assertValidSkillId` tightened to `/^[a-z][a-z0-9-]*$/` so digit-first ids ("99-bottles") and uppercase ids ("WebSearch") are rejected. The digit case was accepted previously even though it breaks the AgentSkills.io convention this layer follows. Two new test cases. * Drift guard broadened: `agent-templates-web.test.ts` now iterates every `AGENT_TEMPLATES` entry and asserts that any `defaultSkills` member is in `KNOWN_SKILLS`. Catches a template-skill mismatch at test time rather than at the runtime guard in `regenerateOpenClawConfig` (which only fires when a user instantiates the template). * `?? []` defense-in-depth on `agent.skills` documented inline — the column is `notNull().default('[]')`, so the null path is unreachable post-migration; the fallback is there to keep an in-flight regenerate race quiet rather than throwing an opaque TypeError. * Self-contradicting comment in `web-agents.ts` removed ("No allowedTools listed here" sat above `allowedTools: [...]`). * `web-search` SKILL.md: Safety section moved ahead of Output format so the model attends to it earlier in the prompt. * Doc examples in `create-market-monitor-agent.mdx` rephrased to be evergreen ("this quarter", "in our industry") instead of bound to specific 2026 events.
2ef0662 to
06d916d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SKILL.mdwith YAML frontmatter, six-tier loading precedence, per-agent allowlist viaagents.list[].skills— as Pinchy's composition unit for agent capabilities.pinchy-webtemplate: Market & News Monitor, lands in the existingmarketing-webcategory. Resolves the gap that triggered this whole initiative —pinchy-webwas the last external plugin without templates.defaultSkillsfield is additive, behavior preserved.What changes
agents.skills jsonbcolumn (migration 0040). Default[]. Existing rows seeded with[].KNOWN_SKILLSconst + drift-guard test (pairs the const list with on-disk SKILL.md files — same convention asKNOWN_PINCHY_PLUGINS).web-searchwith workflow guidelines forpinchy_web_search/pinchy_web_fetch. Source-grounded, recency-aware, no-fabrication invariants in the body.writeWorkspaceSkill(agentId, skillId, content)materializes SKILL.md to<workspace>/skills/<id>/SKILL.md— the highest-precedence skill tier in OC's loader.regenerateOpenClawConfigwritesagents.list[].skillsfor every agent, always, including empty. Verified in Docker smoke-test against OC 2026.6.5: empty allowlist correctly excludes all 58 bundled OC desktop skills (1password, apple-notes, blucli, bear-notes, ...) — the right default for enterprise agents.AgentTemplate.defaultSkills?: string[]added additively. Drift-guard ensures every entry is aKNOWN_SKILLSmember.market-monitor("Market & News Monitor") inmarketing-web, pluginpinchy-web,defaultSkills: ["web-search"]. Persona-only AGENTS.md; workflow lives in the skill so it can be reused by Phase 2 hybrids (Lead Researcher, Competitive Intelligence, Outreach Drafter).requiresWebaccess badge ("Web · Public search") and permission preview ("Search the public web / Fetch public web pages / Cannot access your private data") forpinchy-webtemplates. Plumbed through/api/templatesandnew-agent-form.tsx.agent.createddetail now snapshotsskillsalongside the existingtemplateId/modelSelection.guides/create-market-monitor-agent.mdx, linked in sidebar.Why this shape
Three closed RFCs (#354 Template Contract, #126 MCP Tool Profiles, #372 Agent-Builder-Agent) are consolidated into master #543 because they all describe the same architecture: composable agent capabilities. OpenClaw 2026.6.5 (bundled in Pinchy v0.6.0) implements the AgentSkills.io spec natively — composer, loader, allowlist, gating, Skill Workshop, ClawHub marketplace. Pinchy gets the mechanics for free; this PR just writes the files and emits the allowlist.
The smoke-test against OC 2026.6.5 confirmed three load-bearing properties:
skill-aonly, Agent B seesskill-bonly)skills: []puts all 58 bundled skills into "excluded"<workspace>/skills/<id>/SKILL.mdis the correct path (openclaw-workspacesource inopenclaw skills list)What's next (out of scope for this PR)
Phase 1 sub-issues already filed and tagged
priority:P1:Phase 2 (hybrid templates: Lead Researcher = Web + Odoo etc.), Phase 3 (generated AGENTS.md, supersedes #354), and Phase 4 (MCP UI supersedes #126, ClawHub integration, Skill Workshop UI supersedes #372) are documented in master #543 — sub-issues filed when those phases start.
Test plan
pnpm test— full unit + integration suite green (6225 passed, 0 failed)pnpm test:db— Drizzle migrations apply cleanly (115 passed)pnpm test:scripts— 126 passedpnpm tsc --noEmit— cleanpnpm lint— 0 errors (warnings are pre-existing)cd docs && pnpm build— Astro build cleanghcr.io/heypinchy/pinchy-openclaw:v0.6.0— verified<workspace>/skills/<id>/SKILL.mdloads, per-agent isolation, empty-allowlist semanticsdocker compose -f docker-compose.yml -f docker-compose.dev.yml up --build), confirm the agent picks up the skill and cites sourcesskills: [](no regression)Tracking
Closes #354 #126 #372. Tracked in #543.