Skip to content

scan: promote to a verb (CLI + MCP) + shared Zod type contracts (types.mjs) - #41

Merged
bdelanghe merged 1 commit into
mainfrom
scan-verb-types
Jun 23, 2026
Merged

scan: promote to a verb (CLI + MCP) + shared Zod type contracts (types.mjs)#41
bdelanghe merged 1 commit into
mainfrom
scan-verb-types

Conversation

@bdelanghe

Copy link
Copy Markdown
Contributor

What — productionize the typing (the two halves you picked)

1. types.mjs — the per-type contracts in ONE Zod source

Each symbol type as a Zod schema — headline (≤65, ≥15, no superlatives), cta
(action-verb + ≤24), meta (70–160), body. audit's deterministic type-scoped checks
now run these
instead of hand-coded length tests. claim stays dynamic (grounding-aware)
in claimFindings(); inferType() lives here too. One place to change what a headline is.

Behavior-preserving: verified the Zod contracts reproduce the old hand-coded checks
12/12 cases (same findings, same scores).

2. scan — promoted from a spike to a real verb

spikes/scan.mjs → a scan VerbSpec in verbs.mjsregistry → CLI bin (scan.mjs /
string-audit-scan) + MCP
. Walks the source, extracts every string literal (acorn AST,
optional; regex fallback), keeps the copy-like ones, infers a type and Zod-validates each
keeper against types.mjs — the same contracts audit uses
. --emit writes a DTCG
content/strings.json (round-trips as a CATALOG= input).

registry = { audit, extract, scan }
$ node scan.mjs   →  18 files · 518 literals · 37 keepers (typed copy) · acorn AST

The surfaces now

scan    (source)   → all static strings → Zod-typed keepers   ┐
extract (HTML)     → DTCG catalog tokens                       ├─ one verbspec registry →
audit   (catalog)  → type-scoped (types.mjs) + prose + …       │   CLI + MCP, shared Zod
report  (Anthropic)→ structured output                         ┘   contracts

Test

  • test.mjs: scan keepers (subset, typed, Zod-validated) + the shared type contracts
    (clean headline passes, over-long headline / non-action-verb cta fail, grounded vs
    ungrounded claim).
  • ci.yml: scan-verb smoke (acorn AST + --emit → audit round-trip) + scan in the MCP
    toolset. No new deps (acorn was already optional).
  • Verified locally: full sequence green; audit output unchanged on the brand catalog.

🤖 Generated with Claude Code

…s.mjs)

Two halves of one change — productionize the typing:

1. types.mjs — the per-type symbol contracts as ONE Zod source (headline ≤65 + no
   superlatives, cta = action-verb + ≤24, meta 70-160, body). The audit's deterministic
   type-scoped checks now run these instead of hand-coded length tests (verified
   behavior-preserving: 12/12 cases match the old checks, scores unchanged); claim stays
   dynamic (grounding-aware) in claimFindings(). inferType() lives here too.

2. scan — promoted from spikes/scan.mjs to a real verb (verbs.mjs) → registry → CLI bin
   (scan.mjs / string-audit-scan) + MCP. Walks the source, extracts every string literal
   (acorn AST, optional; regex fallback), keeps the copy-like ones, infers a type and
   Zod-validates each keeper against types.mjs — the SAME contracts audit uses. --emit
   writes a DTCG content/strings.json (round-trips as a CATALOG= input).

registry = { audit, extract, scan }. test.mjs: scan keepers + the shared type contracts.
ci.yml: scan-verb smoke (acorn AST + emit + audit round-trip) + scan in the MCP toolset.
README/Surfaces gains Scan; spikes/README drops the (now-promoted) row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bdelanghe
bdelanghe merged commit a297dc0 into main Jun 23, 2026
1 check passed
@bdelanghe
bdelanghe deleted the scan-verb-types branch June 23, 2026 20:15
@github-project-automation github-project-automation Bot moved this from Todo to Done in Front Desk Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant