# Authorship Validator

> |

- **Type:** Skill
- **Install:** `agentstack add skill-napnap11-claude-skills-authorship-validator`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [napnap11](https://agentstack.voostack.com/s/napnap11)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [napnap11](https://github.com/napnap11)
- **Source:** https://github.com/napnap11/claude-skills/tree/main/authorship-validator

## Install

```sh
agentstack add skill-napnap11-claude-skills-authorship-validator
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Authorship Validation

## Gather context first

This skill ships standalone, so it can't assume your project's conventions, house style, or preferences the way it could for its author. Before doing the main work:

1. **Auto-detect what you safely can** from the repo — language/stack, base branch, build/test commands, existing config and docs. Never ask for something you can read for yourself.
2. **Ask, don't assume, for the rest.** Where an input, convention, or preference would change the result and you can't reliably detect it, ask ONE concise `AskUserQuestion` (put a sensible default first, labelled Recommended) instead of guessing. The user has less context than this skill's author assumed — a wrong silent default is worse than a quick question. Don't ask about things you can detect, and don't ask more than you need.

For this skill, confirm up front (only the items you can't already detect):
- **Submission scope + the starter-code boundary** — which directory/files are the candidate's own work versus take-home scaffold or starter code you must NOT attribute to them. Auto-detect the repo root; ask when the boundary is unclear, because judging provided scaffold as their authorship corrupts every signal.
- **Claimed language/level + the take-home brief** — what they were asked to build and at what seniority. Skill-ceiling discrepancy, README-absence, and orphaned-feature signals are meaningless without this, and it can't be read from the code.
- **The `` label + report destination** — what to name `AUTHORSHIP_REVIEW_.md` (candidate handle / ticket / `submission`) and whether to write the file at all or just report the verdict inline.
- **Depth/mode** — full walk (8 signals + verbatim public-source search + pressure-test design) versus a static-only lean, and whether GitHub Code Search / WebSearch is actually available for the verbatim sweep (if not, say so rather than silently skipping it).

## How this runs

This skill lives in the **main conversation**, and inline is the default. The interactive spine has to stay here regardless of mode: the scope check (Process step 0), any clarifying `AskUserQuestion`, the verdict, and the final gate ceremony all require talking to the user.

Two stretches of the job are pure non-interactive compute — the 8-signal walk and the verbatim public-source sweep. By default you grind through both **inline, in this context**. They are *also* the two stretches that parallelize cleanly, so they are the natural opt-in targets:

| Part | If the user opts into fan-out | Why it parallelizes |
|---|---|---|
| The 8 static signals + AI tells | one agent per signal, each returning that signal's verdict (✓/⚠/✗) with evidence | 8 independent passes over the same repo; running them serially is just latency |
| Verbatim public-source search (signal 8) | one agent per distinctive phrase | a single phrase rarely surfaces the source; independent queries cover more ground |

**Before spawning any subagent or Workflow, stop and ask the user** — for example:

> This submission is large ([N files / many signals]). I can do the 8-signal walk and verbatim search inline here (cheaper, slower) or fan them out as [M] parallel agents (faster, more tokens). Which do you want?

Spawn subagents/workflows only after an explicit yes. If the user declines or doesn't answer, do the whole job inline.

**If — and only if — the user opts into fan-out:** Workflow `agent()` calls run **headless in the background**. They cannot call `AskUserQuestion`, cannot talk to the user, and cannot write files. So every gate, scope check, clarifying question, and **every file write** (`AUTHORSHIP_REVIEW_.md`) stays in the main loop. The workflow only reads code, marks signals, and runs searches, then hands back structured results; you do the weighing, pick the verdict, design the pressure-test, and write the report. Set `model: 'opus'` on every `agent()` call (never let a lighter tier leak in), and pass everything in through `args` — Workflow scripts have no `Date.now` / `Math.random` / filesystem access, so timestamps and file writes only happen back in the main loop.

## Arguments

Read `$ARGUMENTS`:
- A **candidate name / handle / ticket / PR number / commit ref** → use it as `` for the output file `AUTHORSHIP_REVIEW_.md`.
- A **submission root / file path** → scope the review to that directory or file.
- A **mode hint** — "static only" / "report only" → deliver the static lean plus the pressure-test design without over-claiming certainty beyond what code review can support (that ceiling is the default anyway).
- Empty → default the submission root to the repo cwd and `` to `submission` (or the candidate's name, if you know it), but confirm both in the scope step if the repo holds more than the candidate's own work or the candidate's identity is unclear.

## Philosophy

There is exactly one question to answer: **did the candidate write this code, or did they mostly generate it with an AI and hand it in?**

Static review of code-as-artifact **cannot prove authorship.** A clean, correct, well-tested submission could be entirely hand-typed, entirely AI-generated, borrowed from a friend, or any blend of the three. The signals below mark *suspicion* and *direction* — nothing more. The one filter that actually resolves it is the in-person pressure-test. So the work splits in two: (1) weigh the static signals honestly without over-claiming; (2) design the concrete pressure-test that closes the question. That pressure-test design is the real deliverable — build it like the product, not a footnote.

You do NOT score the code (that belongs to the /review-interview rubric) and you do NOT move the technical score. You settle the authorship reasoning and hand back a gate recommendation.

Do NOT edit source. Do NOT touch `interview_result.md`, `REVIEWED.md`, or any other review file. The only thing you write is `AUTHORSHIP_REVIEW_.md`.

## Prime Directives

1. **Consistency is NOT evidence of human authorship.** The classic reviewer mistake: "every signal is internally consistent → must be human." A single AI pass is *also* internally consistent — usually more so. Uniform style, uniform comment cadence, uniform error-handling shape, one tidy commit: all of that fits one generation at least as well as iterative human work. Consistency carries almost no information. Do not bank it as pro-human.
2. **The human fingerprint is inconsistency where a generator would be uniform.** Hunt for the spots a from-scratch AI pass would smooth over but this submission did not: formatter failures clustered in some files and not others (an import auto-dropped at the cursor instead of alphabetized — a hand-editing tell); one helper written in a different idiom than its neighbors; a TODO to self; a `FIXME`; a comment justifying a non-obvious *local* decision. These earned, idiosyncratic, locally-motivated traces lean human. Their *absence* on otherwise-polished work leans generated.
3. **Static review tops out at MEDIUM confidence.** Never declare "definitely human" or "definitely AI" with HIGH confidence on code alone. A verbatim public-source match (3+ disjoint hits on one tutorial) lets you go higher on the AI/copied side. Short of that, the honest ceiling is MEDIUM, and what you hand the hiring team is "here's the lean plus the gate that settles it."
4. **The pressure-test decides.** Every report closes with a concrete, line-grounded, 20–30 minute in-person plan. No hand-waving "ask them about their code." Point at real lines in *this* repo.
5. **Authorship is a gate, not a score.** Never propose moving the technical score. A perfect-scoring submission can still fail the gate; a middling one can clear it.

## Signals that are NOT diagnostic (inference traps — name them, then discount)

- **Internal consistency** (Directive 1).
- **Form/Thought asymmetry BALANCE.** A *skew* (high form %, low thought %) flags form-over-thought — a paste of disparate sources, or a non-coder leaning on AI for the easy parts. But a *balanced* split is NOT pro-human; a fully-generated submission balances too. Balance → neutral, not human.
- **A lone bulk commit on its own.** Candidates routinely squash before submitting. Weak by itself; it needs corroboration (`git log --shortstat`: genuine iterative work touches each file 3–8 times, a one-shot paste touches each file once). Single-commit + each-file-touched-once + a message ending in `finish`/`final`/`initialize`, all on one day, is a far stronger combination than commit count alone.

## The 8 static signals (walk every one, mark ✓ no-concern / ⚠ mild / ✗ strong)

1. **Skill-ceiling discrepancy.** Production-grade moves (JWT method-check, bcrypt cost tuning, timing-attack defense, transactional writes, hexagonal layering) sitting next to beginner mistakes (free-text dates, no search LIMIT, no input validation, `alg:none`-vulnerable parse). Real authors hold a *consistent* ceiling — they know both the senior moves and the basics, or neither. Sharp discontinuities point to a paste of disparate sources.
2. **Comment-to-code voice.** BOTH extremes are AI-shaped: zero comments, OR verbose comments that just restate the signature ("this function validates the input"). Real authors leave *some* voice — a TODO, a FIXME, a comment that explains one non-obvious choice.
3. **Naming consistency.** Mixed acronym casing inside one struct (`NationalId` beside `PatientHN`) = paste from multiple sources. Internally consistent casing, even if non-idiomatic, leans single-author.
4. **Test-to-code skill match.** Tests shouldn't out-skill the code they cover (or the reverse). Mid-tier test idioms wrapped around beginner-mistake handlers is suspicious.
5. **Git history shape.** `git log --oneline` + `git log --shortstat`. Iterative work (20–50 commits across the take-home window, each file touched 3–8 times) leans human; one bulk drop touching each file once leans paste. Squash caveat applies (see traps).
6. **README absence + sophisticated everything else.** Someone who ships transactional GORM with sentinel errors knows what a README is. A conspicuous absence on otherwise-polished work hints at "I didn't write the rest either."
7. **Tutorial / sample-app artifacts.** `MyUser`/`ExampleHandler` names, leftover example data, commented-out sample chunks, unused imports that imply paste from a bigger codebase, identical phrasing across 3+ disjoint comment blocks.
8. **Verbatim match to public sources.** Actually run it (WebSearch / GitHub Code Search) on 2–3 distinctive phrases: a custom error message, a non-trivial helper signature, a distinctive query expression, an idiosyncratic comment. 3+ disjoint verbatim hits on one tutorial = that's the source. Log the searches you ran and the hits.

## Additional AI-generation tells (modern-model signatures)

- **Em-dashes (—) in prose / comments / README.** A strong typographic signature of model output, especially when clustered in boilerplate, tests, and docs.
- **Decorative Unicode separators** in source/tests: box-drawing rules (`─── section ───`, `═══`), check/cross glyphs as section markers, sparkle/emoji headers. Humans rarely hand-type these as comment dividers.
- **`{" "}` JSX whitespace-artifact nodes** (frontend) — `grep -rn '{" "}' src/`; more than 5 hits inside JSX blocks is a cheap "not hand-written" signal.
- **Over-uniform comment cadence** — every function fronted by a one-line WHAT-comment of identical shape.
- **Formatter heterogeneity = human fingerprint (read the direction correctly).** A from-scratch AI pass emits uniformly formatter-clean output (`gofmt`/`prettier`/`black`). So: *uniformly clean* formatting is neutral-to-slightly-generated; *file-by-file formatter failures* (an import wedged inside the stdlib block in some files but not others, not even sorted) are a hand-editing tell — they lean human. Run the formatter in `-l`/check mode and look at WHERE it fails.
- **Orphaned-but-correct features.** A feature built correctly but never wired into the request path is genuinely ambiguous: human-ran-out-of-time vs. AI-generated-a-feature-it-never-integrated. Do NOT read authorship off it — make it the #1 live pressure-test ("wire it now").
- **"Textbook" structure with zero idiosyncrasy** — the canonical layout straight from the framework docs, no personal organizational quirks anywhere.

## Process

0. **Confirm scope.** Auto-detect what you can — repo root, language/stack, git history, any existing prior-review file (`interview_result.md`, `REVIEWED.md`, or similar) — then batch whatever's left from the "Gather context first" list (starter-code boundary, claimed language/level + brief, `` + report destination, depth/mode) into ONE clarifying `AskUserQuestion` with sensible defaults. If a prior review exists, read it — but treat its authorship conclusion as a hypothesis to challenge, not a fact to inherit. (Main loop — the clarifying `AskUserQuestion` happens here.)
1. **Read the code yourself.** Open the highest-logic files (services, handlers, middleware, models, tests, entrypoint, Dockerfile, infra, README, API docs). Never trust a quoted snippet — verify every cited file:line by opening it.
2. **Git forensics.** `git log --oneline --all`, `git log --shortstat`, and where it helps `git log -p` on key files. Note commit count, time spread, per-file touch counts, message style.
3. **Walk all 8 signals + the AI tells.** Mark each ✓/⚠/✗ with one sentence of evidence (file:line) on any ⚠/✗. **Default: do this inline, signal by signal, in this context.** If the user opted into fan-out, run it as the parallel-signal Workflow below instead, then consolidate the ✓/⚠/✗ table in the main loop.
4. **Run the verbatim search.** Log the queries and hits (or clean). **Default: run the 2–3 phrase searches inline.** If the user opted into fan-out, dispatch them as the search-sweep Workflow below.
5. **Discount the non-diagnostic traps explicitly** (consistency, asymmetry balance, lone single-commit). State that you did.
6. **Weigh + verdict.** Choose the lean and the confidence. Name the *single most decisive piece of evidence* in either direction.
7. **Design the pressure-test** (below).

### Signal walk — opt-in parallel fan-out

By default, walk the 8 signals (with the AI tells folded into the relevant ones) inline, one after another, marking each ✓/⚠/✗ as you go. They are independent passes over the same submission, so on a large job they fan out cleanly. **Only if the user opted into subagents**, run this Workflow so each signal is evaluated in parallel by an independent agent, then consolidate the ✓/⚠/✗ table in the main loop. Background agents read the repo and return findings only — they never ask the user anything and never write files.

```js
export const meta = {
  name: 'authorship-validator-signals',
  description: 'Parallel walk of the 8 static authorship signals plus AI tells over a submission',
  phases: [{ title: 'Analyze' }],
}
const SIGNAL_SCHEMA = {
  type: 'object',
  properties: {
    signal: { type: 'string' },
    mark: { type: 'string', enum: ['no-concern', 'mild', 'strong'] }, // ✓ / ⚠ / ✗
    evidence: { type: 'string' },                                      // one sentence, file:line on any concern
    citations: { type: 'array', items: { type: 'string' } },          // verified file:line refs
    leans: { type: 'string', enum: ['human', 'generated', 'neutral'] },
  },
  required: ['signal', 'mark', 'evidence', 'leans'],
}
const SIGNALS = [
  { key: 'skill-ceiling', spec: 'Skill-ceiling discrepancy: production-grade moves coexisting with beginner mistakes. Sharp discontinuities suggest paste from disparate sources. Real authors are consistent in their ceiling.' },
  { key: 'comment-voice', spec: 'Comment-to-code voice: BOTH zero comments AND signature-paraphrasing comments are AI-shaped. Real authors leave some voice (TODO, FIXME, a comment explaining one non-obvious choice). Also flag em-dashes in prose/comments and over-uniform one-line WHAT-comment

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [napnap11](https://github.com/napnap11)
- **Source:** [napnap11/claude-skills](https://github.com/napnap11/claude-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-napnap11-claude-skills-authorship-validator
- Seller: https://agentstack.voostack.com/s/napnap11
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
