vt-c-inbox-qualify¶
Pre-qualify inbox items and show pending proposals dashboard. Scans intake/pending/ for active proposals, then analyzes inbox articles, categorizes them, and routes to knowledge library, intake proposals, or archive.
Plugin: core-standards
Category: Other
Command: /vt-c-inbox-qualify
/vt-c-inbox-qualify — Knowledge Inbox Pre-Qualification¶
Pre-qualify raw external knowledge (articles, blog posts, community patterns) dropped into intake/inbox/ for routing into the toolkit's intake pipeline.
When to Use¶
- You saved a markdown article and dropped it into
intake/inbox/ - You want to triage accumulated inbox items into the knowledge library or intake proposals
- You need to qualify external content before it enters the structured intake pipeline
- You want a quick overview of all pending proposals across intake/pending/ subdirectories
Invocation¶
/vt-c-inbox-qualify # Process up to 10 inbox items (default)
/vt-c-inbox-qualify --batch 5 # Process only 5 items
Prerequisites¶
intake/inbox/directory exists in the toolkit rootintake/knowledge/directory exists with category subdirectoriesintake/pending/from-research/directory exists for toolkit proposalsintake/pending/from-projects/directory exists for project proposalsintake/pending/from-rca/directory exists for RCA proposalsintake/pending/bugs/directory exists for bug reportsintake/archive/directory exists for rejected items
Execution Instructions¶
Step 0: Pending Proposals Dashboard¶
Scan intake/pending/ subdirectories for active proposals to give the user a complete picture of all actionable items before processing the inbox. This step is read-only — it does not modify, route, or process any files.
- Use Bash to list each pending subdirectory:
Filter each to
ls "intake/pending/from-projects/" ls "intake/pending/from-research/" ls "intake/pending/from-rca/" ls "intake/pending/bugs/".mdfiles only. Exclude.gitkeepand hidden entries (.backups/).
If a subdirectory does not exist or is inaccessible, skip it silently (EC-010).
-
For each
.mdfile found, read only the YAML frontmatter (up to the closing---). Extract:date,severity,target_skill,toolkit_proposal_status, and the first# Headingas title. -
Filter out terminal statuses — skip files where
toolkit_proposal_statusis any of:applied,rejected,rejected-at-gate,qualified,completed,resolved,spec-created,reviewed.
Keep files with proposed, pending, needs-modification, deferred-to-spec, or no status field.
Note: This status filter matches
toolkit-reviewStep 1c (lines 95-105). If new statuses are added to the proposal lifecycle, both locations need updating.
If no active proposals found in any subdirectory:
Proceed to Step 1.If active proposals found, display:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Pending Proposals: N active across intake/pending/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
from-projects/ (X)
YYYY-MM-DD severity target_skill Title from first heading
from-research/ (X)
YYYY-MM-DD severity target_skill Title from first heading
from-rca/ (X)
YYYY-MM-DD severity target_skill Title from first heading
bugs/ (X)
YYYY-MM-DD severity target_skill Title from first heading
→ Process proposals: /vt-c-toolkit-review
→ Triage bugs: /vt-c-triage-bugs
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Omit the item lines for subdirectories with 0 active proposals — show only the header with (0).
- Proceed to Step 1 regardless of what was found.
Step 1: Scan Inbox¶
- Use Bash to list the inbox directory:
Filter results to
.mdfiles, excluding.gitkeep.
Do NOT use the Glob tool for this scan — Glob silently excludes filenames containing spaces, causing items to be missed without error.
- Count discovered items
If no .md files found:
If items found, display:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Inbox Scan: N items found
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- If
--batch Nargument provided, limit to first N items - If more than 10 items and no
--batchargument, process first 10 and note remainder:
Non-markdown files (EC-002):
If non-.md files are found in intake/inbox/, warn:
Step 2: Analyze Each Item¶
For each inbox item, read and classify:
2a: Read Content¶
- Files under 1000 lines: Read the full file
- Files over 1000 lines (EC-005): Read first 100 lines + last 20 lines
2a-bis: Input Validation¶
Before processing, validate the file:
1. If YAML frontmatter exists: parse it. If parsing fails (malformed YAML) → classify as archive with note "Malformed YAML frontmatter — skipping to prevent injection"
2. Sanitize any extracted title for slug generation:
- Strip path traversal sequences: .., /, \
- Strip shell-dangerous characters: <, >, |, *, ?, ", ', `, $, ;, &
- Truncate to 50 characters
- Replace spaces with hyphens, lowercase
3. If target_skill is extracted from content: validate it exists in the toolkit's skill manifest (plugins/core-standards/.claude-plugin/skill-symlinks.manifest). If not found → set to tbd with note "target_skill not in manifest"
4. Check for path traversal in any extracted file paths: reject values containing .. or absolute paths outside the toolkit root
2b: Extract Metadata¶
From the content, extract:
- Title: From the first H1 heading (# Title), or from the filename if no H1 found
- Source URL: From any URL in the first 10 lines, or empty if not found
- Tags: 3-5 keywords extracted from content topics
- Summary: One-line AI-generated summary of the article's main point
2c: Classify Relevance¶
Classify each item into one of three categories based on content analysis:
| Classification | Criteria | Destination |
|---|---|---|
| toolkit-proposal | Directly actionable for improving the toolkit: new skill patterns, agent improvements, workflow enhancements, security patterns | intake/pending/from-research/ + intake/knowledge/{category}/ |
| reference | Useful knowledge but not immediately actionable: general AI articles, background reading, techniques that may be useful later | intake/knowledge/{category}/ |
| archive | Not relevant to the toolkit: unrelated topics, outdated content, duplicates, empty files | intake/archive/ |
2d: Assign Category¶
For items classified as toolkit-proposal or reference, assign a category:
| Category | When to Use |
|---|---|
patterns |
Coding patterns, skill patterns, agent patterns, workflow patterns |
tools |
Tool configurations, CLI techniques, IDE integrations, MCP servers |
workflows |
Process improvements, methodology articles, development workflows |
If the content doesn't fit these categories (EC-007), note the suggested custom category. The user can approve or override during interactive approval.
2e: Generate AI & Tooling Update Entry¶
For items classified as reference or toolkit-proposal, check whether the content describes an AI or tooling update relevant to the VisiTrans team. Indicators include:
- Claude Code features, hooks, permissions, IDE integrations
- MCP server developments, new tools, protocol changes
- Claude API changes, Anthropic SDK updates, model releases
- General AI development tools, SDKs, frameworks
- Development workflow tooling, CI/CD innovations, automation
If indicators found, use AskUserQuestion: - Yes — Generate update entry → proceed with entry generation below - No — Skip → continue to Step 2f (normal routing)
Entry generation (when confirmed):
-
Generate slug:
YYYY-MM-DD-kebab-title(max 60 chars, lowercase). If a file with that slug already exists indocs/ai-updates/, append-2,-3etc. -
Assign AI update category (one of):
| Category | When to Use |
|---|---|
claude-code |
Claude Code CLI features, hooks, permissions, IDE integrations |
ai-tooling |
General AI development tools, SDKs, frameworks |
mcp |
Model Context Protocol servers, tools, resources |
api |
Claude API, Anthropic SDK, model releases |
workflow |
Development workflow changes, CI/CD tooling, automation |
- Commentary prompt — use AskUserQuestion:
- Add commentary now → use AskUserQuestion with free-text input to capture the commentary
-
Edit later in IDE → insert
<!-- Add your commentary here -->placeholder -
Write entry file to
docs/ai-updates/YYYY-MM-DD-slug.mdusing this template:
---
title: "[Entry Title]"
date: "YYYY-MM-DD"
tags: [tag1, tag2]
category: claude-code
source_url: "https://..."
source_title: "Original Article Title"
---
## Summary
[AI-drafted 2-3 sentence summary of the update from the source content]
## Key Details
- [Key detail 1]
- [Key detail 2]
- [Key detail 3]
## Why Rolf Thinks This Matters
[User's commentary or <!-- Add your commentary here -->]
## Further Reading
- [Source Title](source_url)
- Update
.index.json: Readdocs/ai-updates/.index.json, parse as JSON array, append a new entry object, write back:
{ "slug": "YYYY-MM-DD-slug", "title": "Entry Title", "date": "YYYY-MM-DD", "tags": ["tag1", "tag2"], "category": "claude-code", "summary": "AI-drafted summary", "source_url": "https://..." }
Edge cases for entry generation:
- No source URL (EC-1): Use null for source_url in JSON; omit the Further Reading section link but keep source_title if available
- .index.json missing (EC-3): Create it with a single-entry array
- .index.json malformed (EC-4): Log warning, backup existing file to .index.json.bak, create fresh with the new entry
- Long article >1000 lines (EC-6): Generate summary from first 100 + last 20 lines (consistent with Step 2a behavior)
- Multiple categories applicable (EC-7): Use the most specific category; capture secondary topics in the tags field
After writing the entry and updating the index, continue with the normal classification routing (Step 2f onward). The item is still routed to intake/knowledge/ or intake/archive/ as usual — the AI update entry is an additional output.
2f: Detect Empty Content (EC-008)¶
If the file has no substantive content (empty, only whitespace, or only a YAML frontmatter block with no body):
- Auto-classify as archive
- Note: "No substantive content"
2g: Detect Duplicates (EC-004)¶
Check if an item with a very similar title already exists in intake/knowledge/:
Step 3: Present Summary Table¶
Display the analysis results for all items:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Qualification Results
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
| # | File | Classification | Category | Summary |
|---|------|---------------|----------|---------|
| 1 | claude-code-patterns.md | toolkit-proposal | patterns | New fork-safe skill pattern for ... |
| 2 | ai-industry-overview.md | archive | — | General AI industry report, no toolkit relevance |
| 3 | mcp-server-guide.md | reference | tools | Guide to building MCP servers with ... |
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
If any duplicates were detected (EC-004), append a warning:
⚠ Possible duplicate: "claude-code-patterns.md" is similar to existing
intake/knowledge/patterns/2026-02-15-claude-patterns.md
Step 4: Interactive Approval¶
Process each item one at a time using AskUserQuestion:
Item 1 of N: claude-code-patterns.md
Classification: toolkit-proposal → intake/pending/from-research/ + intake/knowledge/patterns/
Summary: New fork-safe skill pattern for handling permission denials
Use AskUserQuestion: - Approve — Route as proposed - Change category — Keep classification but change category (e.g., patterns → workflows) - Reclassify — Change classification entirely (e.g., toolkit-proposal → reference) - Skip — Leave in inbox for later
If user selects "Change category": Use AskUserQuestion to pick the new category: - patterns - tools - workflows
If user selects "Reclassify": Use AskUserQuestion to pick the new classification: - toolkit-proposal — Will create intake proposal + move to knowledge - reference — Move to knowledge library only - archive — Move to archive
Step 5: Route Approved Items¶
For each approved item, execute the routing:
5a: Add Qualification Frontmatter¶
For items WITHOUT existing YAML frontmatter:
Prepend frontmatter to the file content:
---
title: "[extracted title]"
date_saved: "YYYY-MM-DD"
qualified_date: "YYYY-MM-DD"
source_url: "[extracted URL or empty]"
category: [assigned category]
relevance: [toolkit-proposal | reference | archive]
tags: [extracted, keyword, tags]
summary: "[AI-generated one-line summary]"
---
[original content unchanged]
For items WITH existing YAML frontmatter (EC-001):
Preserve all existing fields. Add only the missing qualification fields:
- qualified_date
- category
- relevance
- summary
- tags (merge with existing tags if present)
Never overwrite existing values.
5b: Route the File¶
Use git mv to move the file to its destination (NF-002 — preserves git history):
toolkit-proposal:
reference:
archive:
CRITICAL: Before running git mv, check for uncommitted changes to the target file. If the file was just modified (frontmatter added), stage the changes first:
5d: Update Knowledge Index (SPEC-071)¶
After routing to intake/knowledge/{category}/, update the knowledge index so the new document is immediately discoverable:
-
Create
.summaries/directory if it doesn't exist: -
Read the newly routed document and parse its frontmatter (added in Step 5a)
-
Generate summary JSON per SPEC-070 schema:
- Extract key topics from H2 headings (up to 8)
- Detect document type (transcript if 3+
**[MM:SS]speaker patterns found) - Build summary with: version, generated_at, source_file, document_type, title, author, date_saved, category, relevance, tags, summary, key_topics, word_count, deep_evaluated (false), frontmatter_present
-
Write to
intake/knowledge/{category}/.summaries/{filename_without_ext}.json -
Update category index:
- Read existing
{category}/index.json(or create new if first document) - Add entry for the new document
- Sort documents by date_saved descending
-
Regenerate
{category}/index.mdfrom index.json -
Update top-level index:
- Read existing
intake/knowledge/index.json - Update the category's count, top_tags (top 3 by frequency), and recent (most recent filename)
-
Regenerate
intake/knowledge/index.md -
Stage generated files:
Skip this step for items routed to intake/archive/.
5c: Create Intake Proposal (toolkit-proposal only)¶
When an item is classified as toolkit-proposal, also create a proposal file:
Where [slug] is a kebab-case version of the article title (max 50 chars).
Use the standard intake proposal frontmatter format:
---
type: research-finding
date: YYYY-MM-DD
source: inbox-qualify
source_path: intake/knowledge/[category]/[filename]
target_skill: "[identified from content analysis, or tbd]"
severity: medium
category: new-pattern
toolkit_proposal_status: proposed
tags: [from, qualification, analysis]
---
# Proposal: [Title from article]
**Source**: intake/knowledge/[category]/[filename]
**Type**: research-finding
**Priority**: [HIGH | MEDIUM | LOW based on analysis]
## Finding
[Summary of what the article describes and why it's relevant to the toolkit]
## Suggestion
- [Specific action 1]
- [Specific action 2]
## Action
- [ ] Review
- [ ] Implement
Step 6: Summary Report¶
After all items are processed, display:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Inbox Qualification Complete
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Processed: N items
• Toolkit proposals: X → intake/pending/from-research/
• Reference: Y → intake/knowledge/
• Archived: Z → intake/archive/
• Skipped: W (remaining in inbox)
Remaining in inbox: M items
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NEXT STEPS:
• Deep evaluate: /vt-c-content-evaluate --scan-knowledge
• Review proposals: /vt-c-toolkit-review --status
• Implement approved proposals: /vt-c-research-implement
• Process remaining inbox: /vt-c-inbox-qualify
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Edge Cases Reference¶
| ID | Scenario | Handling |
|---|---|---|
| EC-001 | Item already has YAML frontmatter | Preserve existing, merge qualification fields (Step 5a) |
| EC-002 | Non-markdown file in inbox | Skip with warning (Step 1) |
| EC-003 | Inbox is empty | Display "Inbox empty" and exit (Step 1) |
| EC-004 | Duplicate content detected | Flag in summary table, let user decide (Step 2g, Step 3) |
| EC-005 | File exceeds 1000 lines | Read first 100 + last 20 lines (Step 2a) |
| EC-006 | Processing interrupted mid-run | Already-routed items stay routed; unprocessed remain in inbox |
| EC-007 | Category doesn't match predefined set | Allow custom category via AskUserQuestion (Step 4) |
| EC-008 | Empty or template-only file | Auto-classify as archive: "No substantive content" (Step 2f) |
| EC-009 | Filenames with spaces | Use Bash ls instead of Glob tool — Glob silently excludes these files (Step 1) |
| EC-010 | Pending subdirectory missing or inaccessible | Skip that subdirectory silently in Step 0 |
Integration Points¶
| Skill | Relationship |
|---|---|
/vt-c-content-evaluate |
Deep evaluation of classified items for actionable patterns |
/vt-c-research-ingest |
Also scans intake/inbox/ as a fourth source (FR-008) |
/vt-c-toolkit-review |
Reviews proposals generated by this skill |
/vt-c-research-implement |
Implements approved proposals |
docs/ai-updates/ |
AI update entries generated during qualification (Step 2e) |
/vt-c-triage-bugs |
Processes bugs shown in Step 0 dashboard |
Troubleshooting¶
"git mv" fails¶
If git mv fails with "not under version control":
1. Run git add intake/inbox/[filename] first
2. Then retry git mv
If git mv fails with "destination exists":
1. The target file already exists in the destination
2. This may indicate a duplicate — ask the user whether to overwrite or skip
Context limits with many large files¶
If processing many items causes context issues:
1. Use --batch 3 to reduce the number of items processed
2. Process large files individually
3. Run multiple times to clear the backlog
Open Brain Capture (Optional)¶
After qualifying inbox items, if the capture_thought MCP tool is available, capture the qualification summary.
When to capture: After every completed qualification batch.
How:
1. Check if capture_thought tool is available. If not: skip silently.
2. If no items were processed: skip capture.
3. Call capture_thought with: