with one click
with one click
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | content-scan |
| description | Content Candidate Triage |
| version | 1.0.0 |
| scope | enterprise |
| owner | agent-team |
| status | stable |
Invocation: As your first action, call
crane_skill_invoked(skill_name: "content-scan"). This is non-blocking — if the call fails, log the warning and continue. Usage data drives/skill-audit.
Read-only triage tool that scans all ventures for publishable content candidates. Produces a ranked list of article candidates, promotion candidates, and build log gaps. Does NOT draft anything — drafting is done directly by an agent against the terminology doc, then reviewed via /edit-log.
/content-scan # Default: 7-day lookback
/content-scan --days 14 # Custom lookback
/content-scan --save # Also save results to VCMS
Parse $ARGUMENTS:
--days N is present, set LOOKBACK_DAYS to N. Default: 7.--save is present, set SAVE_TO_VCMS to true. Default: false.$ARGUMENTS is empty, use defaults (7 days, no save).Verify CRANE_CONTEXT_KEY is set in the environment. If not, stop: "CRANE_CONTEXT_KEY not set. Launch with crane vc."
Ping crane-context health endpoint. If not 200, stop: "crane-context API unreachable. Cannot run content scan without handoff data." Do not degrade to git-only mode - handoffs are the primary signal.
Read ~/dev/crane-console/config/ventures.json. Store as VENTURE_REGISTRY.
Build a list of active ventures - entries with a non-empty repos array. Skip ventures with "repos": [].
Scan ~/dev/vc-web/src/content/ for published content:
~/dev/vc-web/src/content/articles/*.md. Read frontmatter (title, date, tags) from each file.~/dev/vc-web/src/content/logs/*.md. Read frontmatter (title, date, tags, draft) from each file. Exclude files where draft: true.Store these as ARTICLE_INDEX and LOG_INDEX.
For each venture, count published articles where the venture's name or code appears in tags. Store as ARTICLE_COUNTS (e.g., { ke: 0, dfg: 0, sc: 0, dc: 0, vc: 12 }).
Search VCMS for the most recent content-scan note:
crane_notes(tag: "content-scan", limit: 1)
If a note exists, extract its created_at timestamp as LAST_SCAN_DATE.
Query handoffs created since the last scan. Check if any exist (count > 0).
If zero ventures have new handoffs since the last scan:
crane_schedule(action: "complete", name: "content-scan", result: "skipped", summary: "No new handoffs since last scan", completed_by: "crane-mcp")Fetch all handoffs within the lookback window. Group by venture field. For each venture, store the summary and created_at from each handoff.
Note: Handoffs created from crane-console sessions carry venture=vc even when the work targets another venture. Scan each handoff's summary text for venture names and codes (dc, ke, sc, dfg) and cross-reference mentions to associate handoffs with the correct venture when the venture field doesn't match.
Iterate each active venture in the registry. For each venture, for each repo in its repos array:
# Merged PRs in the lookback window
gh pr list --repo {ORG}/{REPO} --state merged --json number,title,mergedAt \
--jq '.[] | select(.mergedAt >= "'$(date -v-{LOOKBACK_DAYS}d +%Y-%m-%d)'")'
# Closed issues in the lookback window
gh issue list --repo {ORG}/{REPO} --state closed --json number,title,closedAt \
--jq '.[] | select(.closedAt >= "'$(date -v-{LOOKBACK_DAYS}d +%Y-%m-%d)'")'
Store PR titles and counts per venture-repo.
Selective PR body fetching: For PRs whose titles contain any of these keywords (case-insensitive): redesign, migrate, remove, replace, decision, tradeoff, rewrite, new - fetch the full PR body:
gh pr view {NUMBER} --repo {ORG}/{REPO} --json body --jq '.body'
Cap at 5 body fetches per repo. After 5, stop fetching bodies even if more titles match.
For each venture, record:
Evaluate gathered signals using bucket-based assessment. Do not assign numeric scores.
Gating question: Does the material have handoff narrative AND a decision or surprise worth generalizing to readers outside Venture Crane?
For each venture with handoffs in the window, assess:
Produce a one-line headline and a "Why" rationale for each candidate.
Skip this section entirely if LOOKBACK_DAYS < 7.
Gating question: Does an existing build log read like a draft article worth promoting?
Filter LOG_INDEX to logs that are:
For qualifying logs, assess:
Gating question: Did something ship (merged PR with handoff narrative) with no matching build log?
For each venture with merged PRs in the window:
LOG_INDEX with a matching venture tag and a date within the window).ARTICLE_INDEX for matching venture tags and similar topics)If a venture has zero published articles (ARTICLE_COUNTS[code] == 0), boost its candidates one confidence level:
This integrates the gap signal into the ranking. Do not present it as a separate analysis.
Format and display the results:
CONTENT SCAN - {TODAY} - Last {LOOKBACK_DAYS} days
================================================================================
ARTICLE CANDIDATES
--------------------------------------------------------------------
HIGH {CODE} {Headline}
Why: {rationale}
Source: handoff {date}
Note: {venture name} has zero published articles (coverage boost)
MED {CODE} {Headline}
Why: {rationale}
Source: handoff {date}
PROMOTION CANDIDATES (weekly)
--------------------------------------------------------------------
HIGH {CODE} {log-slug} ({date})
Why: {word count} words, substantive surprise section, no article on topic
Action: draft article (then review with /edit-article or /edit-log)
LOG CANDIDATES
--------------------------------------------------------------------
{CODE} {description} - merged PR, handoff exists, no log
Source: PR #{number} merged {date}
COVERAGE GAPS (ventures with zero published articles)
{comma-separated list of venture names}
SIGNAL HEALTH
{code} handoffs: {N} git: {N} PRs {status}
...
================================================================================
Status labels for signal health:
OK - at least 1 handoff existslow activity - handoffs exist but sparse (1 handoff, 0 PRs)no signal - zero handoffs and zero PRsSection omission rules:
If there are zero candidates across all sections, display:
CONTENT SCAN - {TODAY} - Last {LOOKBACK_DAYS} days
================================================================================
No publishable candidates found.
SIGNAL HEALTH
{code} handoffs: {N} git: {N} PRs {status}
...
================================================================================
If SAVE_TO_VCMS is true (from --save flag), save automatically.
If SAVE_TO_VCMS is false, ask: "Save results to VCMS? (y/n)"
If saving:
crane_note(
action: "create",
title: "Content Scan - {TODAY}",
content: "{full output text from Step 5}",
tags: ["content-scan"],
venture: null
)
The note is global (no venture), tagged content-scan so the short-circuit check in Step 2 can find it.
After completing the scan, record in the Cadence Engine:
crane_schedule(
action: "complete",
name: "content-scan",
result: "{result}",
summary: "{summary}",
completed_by: "crane-mcp"
)
Result enum:
success - API healthy, at least one article-grade candidate found (High or Medium)warning - API healthy but zero article-grade candidates (only log gaps or no candidates at all), OR partial API failures during signal gatheringskipped - short-circuited in Step 2 (already recorded there; do not record again)Summary examples:
/edit-log or /edit-article.LOOKBACK_DAYS >= 7. Logs don't change daily.portfolio.showInPortfolio is false) are skipped automatically because they have repos but should not produce public content candidates. If a stealth venture's work generates a candidate, omit the venture name and flag it: "Candidate from internal venture - discuss with Captain before proceeding."