Analyze web clippings, create resource notes with Layer 1 content, and return lightweight proposals. Handles enrichment, analysis, note creation, and Layer 1 injection so content never flows through coordinator. Worker skill for triage orchestrator.
From para-obsidiannpx claudepluginhub nathanvale/side-quest-marketplace-old --plugin para-obsidianThis skill uses the workspace's default tool permissions.
references/layer1-formatting.mdExecutes pre-written implementation plans: critically reviews, follows bite-sized steps exactly, runs verifications, tracks progress with checkpoints, uses git worktrees, stops on blockers.
Guides idea refinement into designs: explores context, asks questions one-by-one, proposes approaches, presents sections for approval, writes/review specs before coding.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Analyze a single web clipping, create the resource note with Layer 1 content, and return a lightweight proposal.
Key design: This skill creates the resource note AND populates Layer 1 before returning. The full content stays in subagent context - only the proposal flows back to the coordinator.
You receive:
file: Path to clipping in inbox (e.g., 00 Inbox/✂️ Article Title.md)areas: Available areas in vaultprojects: Available projects in vaultReturn a JSON proposal per @plugins/para-obsidian/skills/triage/references/proposal-schema.md.
Key: Use area (single wikilink), project (single wikilink or null), resourceType (camelCase). Include file, type: "clipping", created, and layer1_injected alongside the standard proposal fields.
para_read({ file: "[input file]", response_format: "json" })
Extract frontmatter fields (source, domain, capture_reason, pre-filled areas/projects) from the YAML header in the para_read response. Do NOT call para_fm_get separately — para_read returns the full file including frontmatter.
Also extract existing body content.
CRITICAL: Select tool based on domain. Use ToolSearch to load deferred tools before calling them.
| Domain | Tool | ToolSearch Query |
|---|---|---|
youtube.com / youtu.be | get_transcript (fallback: get_video_info) | "youtube transcript" |
x.com / twitter.com | x_get_tweet (parse tweet_id from URL) | "x-api tweet" |
github.com / other articles | firecrawl_scrape | "firecrawl scrape" |
X/Twitter is MANDATORY enrichment — Web Clipper captures only stubs. Always fetch via X-API regardless of clipping content.
See @plugins/para-obsidian/skills/triage/references/enrichment-strategies.md for the full routing table and constraints.
See @plugins/para-obsidian/references/content-sourcing/url-routing.md for detailed per-domain patterns.
Determine:
resource) or reference (gift, booking, etc.)?article, tutorial, reference, thread, issue, ideavideo, article, thread, documentBefore calling para_create, verify your args object includes these critical fields:
summary — one-sentence description of the resourceareas — wikilink(s) to vault areassource_format — article, thread, video, documentresource_type — article, tutorial, reference, thread, issue, ideaIf any field is missing but you determined a value in Step 3, add it to args now.
This is where content stays isolated. Use para_create with the content parameter to create the note AND inject Layer 1 in a single tool call:
para_create({
template: "resource",
title: proposed_title,
args: { ...fields from validArgs },
content: {
"<content-target-heading>": formattedLayerOneContent
},
response_format: "json"
})
The content parameter maps heading names to body content. The CLI internally creates the note, injects content into the matching section, and auto-commits — all in one invocation. No separate para_commit or para_replace_section calls needed.
Content target heading: Use creation_meta.contentTargets[0] from template fields (typically "Layer 1: Captured Notes"). If template fields were pre-loaded in the prompt context (triage mode), use those directly.
See @references/layer1-formatting.md for Layer 1 content formatting patterns (articles, YouTube, threads).
If para_create fails: Set created: null, layer1_injected: null, and continue with the proposal. The content parameter failure is atomic — no partial state.
During triage: Skip this step entirely. Set verification_status: "pending_coordinator" and verification_issues: []. The coordinator handles verification in Phase 2.5 — it stamps and checks all critical fields from PROPOSAL_JSON.
Standalone callers (non-triage): Call para_fm_get on the created file. Compare each critical field:
| Field | Your intended value | File value | Action |
|---|---|---|---|
summary | from Step 3 | from para_fm_get | MISMATCH → repair |
areas | from Step 3 | from para_fm_get | MISMATCH → repair |
source_format | from Step 3 | from para_fm_get | MISMATCH → repair |
resource_type | from Step 3 | from para_fm_get | MISMATCH → repair |
If any MISMATCH: para_fm_set({ file, set: { ...repairs }, response_format: "json" })
Set verification_status: "verified" (all match), "repaired" (fixed), "needs_review" (empty fields), "skipped" (para_create failed).
Return the lightweight JSON proposal. The resource is already created with Layer 1 populated.
{
"file": "00 Inbox/✂️ Original.md",
"type": "clipping",
"proposed_title": "Title",
"proposed_template": "resource",
"summary": "...",
"created": "03 Resources/Title.md",
"layer1_injected": true,
"verification_status": "verified",
"verification_issues": [],
...
}
The coordinator receives only this ~500 byte proposal, not the 10-20k token content.
| Content Type | Template | Resource Type |
|---|---|---|
| Tutorial/how-to | resource | tutorial |
| News/opinion | resource | article |
| Twitter thread | resource | thread |
| API docs | resource | reference |
| GitHub issue | resource | issue |
| Product page | gift | - |
| Booking confirmation | booking | - |
| Flight/hotel | booking | - |
| Level | Meaning |
|---|---|
high | Clear content, obvious categorization |
medium | Reasonable guess, user may want to adjust |
low | Ambiguous content, multiple valid interpretations |
{
"file": "00 Inbox/✂️ Matt Pocock TypeScript Tips.md",
"type": "clipping",
"proposed_title": "TypeScript 5.5 Inference Improvements",
"proposed_template": "resource",
"summary": "Matt Pocock explains new type inference features in TypeScript 5.5, focusing on const type parameters and improved narrowing in control flow.",
"categorization_hints": [
"Const type parameters preserve literal types without 'as const'",
"Control flow analysis now narrows in more cases",
"New 'satisfies' patterns for type-safe object literals"
],
"area": "[[🌱 AI Practice]]",
"project": "[[🎯 TypeScript Migration]]",
"resourceType": "tutorial",
"source_format": "thread",
"author": "Matt Pocock",
"confidence": "high",
"notes": null,
"created": "03 Resources/TypeScript 5.5 Inference Improvements.md",
"layer1_injected": true,
"verification_status": "verified",
"verification_issues": []
}
| Scenario | Action |
|---|---|
para_create (with content) fails | Set created: null, layer1_injected: null, return error proposal |
| Content empty/unparseable | Create note without content parameter, set layer1_injected: false |
Atomic creation: When using the content parameter, creation and injection are a single atomic operation. If it fails, there's no partial state to clean up.