HarperZ9/articulateExplainer, built from commit c94bf17All repository explainers

Articulate

A writing checker that runs on your own computer and names each pattern it finds.

What it does for you

Articulate reads a draft and points at the exact words that make it read as stock or generated: a corporate verb, an antithesis, a stock connective, an em dash. It tells you whether the draft passes the bar for its kind of writing, and it can record that result so anyone can replay it later. The checks make no network call.

Source: README.md at c94bf17 (version 0.9.0)

Watch

No concept film fits this tool closely yet. The walkthrough below covers it in text, with real commands and output.

Video walkthrough: coming with the next release.

How it works, one step at a time

Scroll, or use the step buttons. The panel follows one short draft through the checker. Every finding, score and verdict below is output from Articulate at commit c94bf17, and the same output came from articulate-writing 0.9.0 installed from PyPI.

  1. 01

    One draft, six findings

    Here is a short blog post. Run articulate check post.md --profile readme --verbose and six spans light up, each with a named rule: a corporate verb, a marketing superlative, a possible triad, an antithesis, a stock connective and an em dash.

    Every finding carries a precision tier. HIGH is the precise device tier. MEDIUM adds register tells. LOW is advisory and never blocks.

    Source: src/articulate/detector.py, scan_lines and GATE_TIERS

  2. 02

    The profile decides what blocks

    The findings stay the same. The profile sets a level, and the level sets which tiers block. readme is "flavored": the three HIGH findings block, so the gate reads blocked and --gate exits 1.

    Switch to narrative and the level is "off": nothing blocks, and the gate reads ok while the findings are still reported. Switch to procedure and the level is "strict": HIGH and MEDIUM both block, five in all.

    Source: detector.py check_text; profiles.py

  3. 03

    A graded score beside the gate

    The texture score is a separate 0 to 100 read of how machine-textured the whole draft is. Each HIGH or MEDIUM finding is worth 8 points per 100 words. Five findings in 57 words gives 70.2, rounded to 70. Uniform sentence lengths, repeated openers, and adverb or passive rates above a threshold add more.

    The score never changes the gate. Under 30 words it returns 0, because there is too little text to say anything.

    Source: detector.py, texture_score

  4. 04

    Find the paragraph, and abstain on the rest

    A whole-file score can hide one generated paragraph in otherwise clean prose. --spans scores each block on its own. The middle paragraph is flagged at 100. The heading and the last paragraph have no findings and fewer than 30 words, so they read unverifiable. The tool abstains and makes no clean claim about them.

    Source: detector.py, MIN_WORDS_FOR_VERDICT = 30; docs/walkthrough.md, step 2

  5. 05

    Record a receipt

    A receipt stores the result with the two things needed to reproduce it: the SHA-256 of the exact text and a fingerprint of the ruleset that ran. It holds no Trusted or Approved field. It certifies that the result can be re-derived, and nothing about authority.

    Source: src/articulate/receipt.py, module docstring

  6. 06

    Replay it

    verify checks the ruleset fingerprint and the text hash, then runs the checker again and compares the findings, gate and texture score with the receipt. Same text, same ruleset, same result: Match, exit 0.

    Edit the receipt's gate, or drop a finding from it, and the re-derived result disagrees: Drift, exit 1. Change one word of the text, or replay under a different ruleset, and there is nothing valid to compare: Unverifiable, exit 2. Try each case in the panel.

    Source: receipt.py, verify_receipt

  7. 07

    Rewrite, then check again

    The fix is to say the concrete thing. The rewrite in the panel was written for this page, outside Articulate's editor. Under the same profile it has no findings, a texture score of 0, and --gate exits 0.

    Articulate's own editor (fix, judge, polish) uses the calling host's model, a backend you configure, or mechanical fixes with no model. Every result names the backend that made it. A rewrite is a suggestion to read against the original.

    Source: README.md, "Edit" and "Editing from a host or the command line"; docs/walkthrough.md, step 4

Walkthrough

Install it, run it once, then use the main feature. Each command below is real, and so is its output.

  1. Install

    Install from PyPI. Python 3.9 or newer; the checker uses the standard library only and makes no network call.

    $ python -m pip install articulate-writing
  2. First run: check a draft

    Check a draft against a profile. With --gate the command exits 1 when high findings block it.

    $ articulate check post.md --profile readme --gate
    [articulate] post.md [readme]: 3 high, 2 medium (blocked)  texture 70/100
  3. Seal a receipt and re-derive it

    Write a receipt for the check, then verify it against the same file.

    $ articulate receipt post.md --profile readme > post.receipt.json
    $ articulate verify post.receipt.json post.md
    [articulate] Match: re-derived 6 findings, gate blocked, texture 70

Output from articulate-writing 0.9.0 installed from PyPI, on the post.md shown above, with the summary line of each command. The first command exits 1 because the gate is blocked.

What it does not do

Source: README.md "Privacy" and "Scientific and mathematical writing"; detector.py texture_score; docs/boundaries.md, at c94bf17

Check what stuck

Answer each one in your head before you open it.

The same draft is blocked under readme and ok under narrative. What changed?

Only the profile's level. The findings are identical; "flavored" blocks the HIGH tier and "off" blocks nothing.

Where does the texture score of 70 come from?

Five HIGH or MEDIUM findings at 8 points each per 100 words, over 57 words: 70.2, rounded to 70. Nothing else added to it here.

Why is the last paragraph unverifiable and not clean?

It has no findings and fewer than 30 words. Below that floor the tool abstains and makes no confident clean claim.

Editing the text gives Unverifiable, while editing the receipt gives Drift. Why the difference?

A changed text no longer matches the receipt's hash, so there is nothing valid to re-derive. A changed receipt still matches the text and ruleset, so the replay runs and disagrees with what the receipt says.