@andresmassello/uscha

中文文档
2.14.1发布于 2026/11/05MIT零依赖构建来源已验证近 30 天下载 2027

Spec-driven development for LLM coding agents: 9 skills + a stdlib evidence engine. Facts block, guesses advise; the human approves.

原始使用文档
文档目录10 节
  1. The problem it solves
  2. What you get
  3. Compatibility matrix
  4. The loop, in short
  5. What makes it different
  6. The diamond — specs are the source code, end to end
  7. Documentation
  8. Developing Uscha itself
  9. History
  10. License

Uscha

Spec-driven development for LLM coding agents. You bring the idea, the method builds the rest. Uscha gives a coding agent a spec to build against, a QA loop that converges instead of looping forever, and a deterministic ledger that records what was measured — never what was claimed.

The agent executes · the method governs · evidence decides · the human approves.

uscha.dev — the method, the five rules, the skills, the library (the diamond thesis, how-it-works diagrams, essay, 2-day dev course, reference, paper).

New here? Start with First use: from install to one measured result — one machine, one small repo, one criterion closed by a real test, and the merge left to you (en español).

npx --yes @andresmassello/uscha@latest install --target claude   # Claude Code
npx --yes @andresmassello/uscha@latest install --target codex    # Codex
npx --yes @andresmassello/uscha@latest install --target cursor   # Cursor
npx --yes @andresmassello/uscha@latest install --target copilot  # VS Code / GitHub Copilot
npx --yes @andresmassello/uscha@latest install --target gemini   # Gemini CLI
npx --yes @andresmassello/uscha@latest install --target cline    # Cline
npx --yes @andresmassello/uscha@latest install --target pi       # pi (Earendil)
npx --yes @andresmassello/uscha@latest install --target all      # every target at once

npx --yes @andresmassello/uscha@latest doctor --target all

The nine skills implement the Agent Skills standard, so the last five targets are the same skills placed under each agent's own documented root. Honest scope: only Claude Code and Codex have been exercised against a real agent — for the rest, that they load is a documented expectation, not a measurement. What is measured is that the files land where each agent documents reading them and that doctor reads them back. INV-GOLDEN-01 is mechanically enforced only on Claude Code (a blocking PreToolUse hook); everywhere else doctor reports it as advisory rather than implying a guard it cannot see. (both stays a legacy alias for codex+claude.) Then, in your project:

npx --yes @andresmassello/uscha@latest init

Requires Python 3.8+ on the machine (the engine is Python stdlib — no pip installs, no runtime dependencies). The npm package is a thin router; the canonical installer is uscha-kit/install-uscha.py. init also writes a minimal, per-repo-type .gitignore when the project has none (kit 2.4.0) — it never lists reports/, the ledger's own evidence.

The kit declares no dependencies and installs none. Since kit 2.7.0 (ADR-052) install ends with an extras report and the installer's doctor repeats it as an advisory section: how the dev loop's QA tools (code-review, judgment-day, improve, the kit default order) resolve on the target machine — through the engine's own resolver, so code-review reads "assumed, harness-provided, not measured" — and whether the optional engram (uscha does not require it) is present, with the commands to add it. Present means usable from Claude: the engram plugin installed and enabled, or an MCP server named engram in the Claude configuration; a bare binary on PATH reads "binary found, not wired into Claude". The MCP check reads only the Claude configuration, for --target codex too. It only reports: it installs nothing, asks nothing and runs none of the commands it prints, and it never changes an exit code.

Kit v2.14.1 · uscha.dev · changelog (the per-release changelogs live in the repo, not in the npm tarball)


The problem it solves

An agent will tell you the tests pass. It will tell you the feature is done. It is often right — and when it is wrong, you find out in production.

Uscha refuses to take the agent's word for anything. Every claim that matters has to be backed by a report the agent did not write: a JUnit file, a coverage report, a linter's output. For tests that is enforced, not hoped for (2.10.0): the engine runs the test command your project DECLARED (test-run), records the run, and its gates honor only the JUnit and coverage files that run wrote — a report written, copied or edited by anyone else is not evidence. What stays trusted is the declared command itself: a config line a reviewer reads. Facts block; guesses advise. A checkbox ticked by hand is recorded as narrated and does not close a criterion. A test named after that criterion, green, in a report a recorded test-run wrote — that closes it.

The result is a readiness score you can actually trust, because you can click any number and see which file, which test, and when.

What you get

Nine skills that drive the method end to end:

SkillWhat it does
/uscha-discoveryIdea → spec package (CONTEXT, SPEC, ADRs, CONSTITUTION, ACCEPTANCE)
/uscha-adr-refineKnown feature → ADR + ACCEPTANCE, by interrogating you first
/uscha-reverse-discoveryExisting system → facts + typed candidates in quarantine; never promoted without a human verdict (brownfield)
/uscha-characterizeCapture a golden suite of current behavior before touching it
/uscha-devloopPlan → build → severity-gated QA loop → PR (stops at the merge)
/uscha-rubricGrade the non-testable (conventions, ergonomics) against a versioned rubric
/uscha-sysdocGenerate a system deck from the ledger
/uscha-miradorBird's-eye HTML dashboard: readiness, trail, acceptance, loops
/uscha-statusOne-line progress readout, in chat

A measurement engine (qa_ledger.py, 62 subcommands, Python stdlib) that ingests evidence from 11 language stacks — maven, gradle, ant, python, node, go, rust, dotnet, cpp, swift, flutter — and computes a readiness score with hard caps and visible provenance.

Compatibility matrix

The target and install-path columns mirror TARGETS/SKILL_ROOTS in the installer. The exercised column is editorial, not generated: last updated 2026-09-20 (ADR-049).

targetagentinstalls toINV-GOLDEN-01exercised against a real agent
codexCodex~/plugins/uschaadvisoryyes
claudeClaude Code~/.claude/skillsenforced (PreToolUse hook, best-effort)yes
pipi (Earendil)~/.agents/skillsadvisoryno — placement + read-back only
cursorCursor~/.cursor/skillsadvisoryno — placement + read-back only
copilotVS Code / Copilot~/.copilot/skillsadvisoryno — placement + read-back only
geminiGemini CLI~/.gemini/skillsadvisoryno — placement + read-back only
clineCline~/.cline/skillsadvisoryno — placement + read-back only

"Exercised" is the column that matters. For every target but Claude Code and Codex, what is measured is that the nine skills land where that agent documents reading them and that doctor reads them back — that they load is a documented expectation, not a measurement. INV-GOLDEN-01 is mechanically attempted only where a blocking pre-tool hook exists; everywhere else doctor reports advisory rather than implying a guard it cannot see.

OShow it is verifiedstatus
LinuxCI matrix (py3.8 + py3.13) + local WSLmeasured
WindowsCI matrix (py3.8 + py3.13) + native localmeasured
macOSCI matrix (py3.8 + py3.13), real runnersmeasured

The loop, in short

  1. Model first. /uscha-discovery (new) or /uscha-adr-refine (known feature) writes the spec package. No code until the package exists.
  2. Build. /uscha-devloop implements against the SPEC, with tests as a guardrail.
  3. QA loop. Independent review passes (maker ≠ checker) run until the change converges — findings at or above the severity gate are fixed, the rest go to ISSUES-DEFERRED.md with their evidence. Since 2.11.0 the engine witnesses each review (review-start stamps the tree it starts on): a gated finding closes only on a later clean review of different source, or -- since 2.14.0 -- by the deferral of its own id, confirmed by a human (ADR-060); and the last review of each tool must have seen the code on disk now (ADR-056). Converge, don't chase zero.
  4. Readiness. One score, one screen: acceptance (measured) 30 · static gate 20 · ADR 15 · coverage 15 · convergence 10 · integration 10, with hard caps that say why they bit and whether the threshold was your requirement or the kit's default.
  5. You decide. The agent proposes, measures and stops at the PR. Merging is a human act, and so is lifting an escalation: since 2.12.0 those commands need --human/--note and refuse inside Claude Code's shell, and a hook keeps a PR a draft while the gate is red (ADR-058).

What makes it different

  • Measured beats narrated. An acceptance criterion closes on a green test that carries its name — never on a checkbox. Stale evidence (a report whose run measured a different source tree) and unwitnessed evidence (a report no recorded test-run wrote) are discarded, not honored — re-derived every time a gate reads them.
  • Absence is not success. A gate that never ran scores UNMEASURED, which is deliberately not the same as a measured zero — and it is not silently forgiven either.
  • Receipts. Every number in the dashboard traces to its evidence: which testcase, which report, which timestamp.
  • Anti-ceremony. Gates stay quiet by default and collapse into one verdict line. The method is enforced by the engine, not by asking the agent to be disciplined.
  • Model-agnostic. The engine never reads tokens, model names or vendor telemetry. Any model-reported number enters through an adapter, never the engine.
  • Field truth for greenfield. In a new system every test payload was invented by the agent that wrote the code, so corpus-run scores a corpus of REAL inputs against the real command and persists the percentage as a fact — advisory until the project declares a budget, a blocking gate once it does (ADR-046).
  • Evidence is executed, not narrated. The smoke run is a report the project's tool writes, not a paragraph an agent types (unlike test reports, a smoke report is still read by path — not yet witnessed by a recorded run, ADR-055): smoke-ingest reads {"checks": [{"name", "ok", ...}]}, a failed check blocks like any fact gate, and an empty or malformed report is refused rather than scored (ADR-047).

The diamond — specs are the source code, end to end

Uscha closes a cycle most spec-driven tools only walk halfway. The spec package plus its behavior ledger is the canonical asset of a system; the code is a regenerable build artifact. An LLM compiles the package into code under a validated contract; reverse discovery decompiles existing code back into curated specs — passing, mandatorily, through the one step no automatic tool can perform: a human verdict.

                THE ASSET (solid) ── it appreciates with every model generation
          ┌───────────────────────────────────────────────────────────────┐
          │   SPEC PACKAGE  +  BEHAVIOR LEDGER  +  IR                     │
          │   SPEC · ADRs · ACCEPTANCE · CONSTITUTION                     │
          │   verdicts: preserve · fix · undefined                        │
          └──────────────┬─────────────────────────────▲──────────────────┘
                         │                             │
        FORWARD          │                             │          REVERSE
        the LLM compiles │                             │   reverse discovery
                         ▼                             │
   ┌─────────────────────────────────────┐   ┌─────────┴─────────────────────┐
   │ compile-validate — output contract, │   │ CURATION · the human gate     │
   │   mechanical only, model-blind      │   │ candidate ─▶ verdict ─▶ ledger │
   │ withheld ORACLE — authored BEFORE   │   │ no verdict → PR blocked,      │
   │   compiling, never in the prompt    │   │   the candidate is NAMED      │
   └─────────────────┬───────────────────┘   └─────────▲─────────────────────┘
                     │                                 │
                     ▼                                 │
   ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐   ┌─────────────┴─────────────────────┐
     CODE (dashed) — build artifact,      │ discover · golden capture         │
     regenerable, disposable          ───▶│ candidates: typed evidence        │
   └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘   │   + confidence                    │
                                          └───────────────────────────────────┘
                                            ▲ also enters here: any LEGACY
                                              system (= 100% drift)

   round trip · bench-roundtrip — how much of the asset the reverse organs re-anchor
   from the compiled code: 0.815 measured (12 archetypes) — names AND behaviour

What each arrow is, in the engine (62 subcommands, all measured):

LegSubcommandsWhat it establishes
Asset → typed graphir-extract, ir-renderthe whole package becomes one canonical IR (M2, ADR-015) — deterministic, UNTYPED is a measurement not an error
Forward, the compilercompile-validate, compile-ingestany model produces code; the engine validates the output contract and never compiles (M3, ADR-016)
Forward, is it the same system?bootstrap-oracle, bootstrap-variance, bencha withheld oracle judges blind compilations — 12 archetypes, 8 PASS · 4 PARTIAL (measured September 2026), four blind compilers across two vendors (Haiku · Sonnet · Opus · OpenAI Codex gpt-5.5), JS included (M4/M5, ADR-017/018/028/029/042)
Reverse, factsdiscover, golden-diff (+ the /uscha-characterize skill)system map + mechanically captured golden; typed candidate observations with evidence class (M1, ADR-013)
Reverse, the human gatecurate, promote, curation-check, bench-curateone verdict per candidate, append-only ledger verified against git; unjudged → pr-ready blocked naming it (ADR-009/010, INV-CURATION-01)
Fidelity, honestlyfidelity, roundtrip, bench-roundtrip, bench-r2per-compiler fidelity vector, id-level round trip, recoverability 0.815, and the noise floor under every variance claim (ADR-014/022/027/030)

Read the numbers the way the repo does. 8 of 12 archetypes (measured September 2026; four blind compilers — Haiku, Sonnet, Opus and OpenAI Codex gpt-5.5) regenerate to the same system under an oracle the compilers never saw — that is the closed loop working. It was 9 of 12 until 1.99.0, when a fourth compiler from a second vendor read one genuinely ambiguous sentence in transformer the other way and lost a case the three Claude-family models had agreed on (ADR-042). The number went down because the bench got harder, and the whole point of the arm was to let it. Since 2.2.0 that headline is a derived fact: qa_ledger.py facts counts the verdict rows of DIAMOND-BENCH.md — the report bench generates over the committed fixture — into SYSTEM-FACTS.json, and facts --check compares every published copy of it against that count. It was added because the project's own homepage said 9/12 for nine releases after the number moved, and every one of those releases was green: the claim sat in one HTML element and its noun in the next, where the gate could not see it. 0.815 is the mean recoverability of the asset from compiled code counting only static and behavioural footing. It read 0.062 until 1.90.0, with the behaviour dimension UNMEASURED, because no oracle case carried an AC tag — a named absence, not a zero. The 12 bench oracles are now curated per case (ORACLE-TAGS-CURATED.json, human-authored; payloads and expectations untouched), so the dimension is measured and the number says the reverse organs anchor names and behaviour; it read 0.828 over three compilers and 0.815 over four, because an entry's recoverability is the mean over its compilations. Every number is published rather than smoothed, and what moved between them was the tagging and the arm, not the code under test. And bench-r2 measured that same-model reruns differ structurally about as much as different models do (aggregate NOISY) — so one earlier variance narrative was retracted. Every claim above is a subcommand you can run; every unmeasured part is labeled. That honesty is the method applied to itself.

Every verdict above is tied to a named criterion, and every one a human judged is tied to the person who signed it — the ledger itself, bench-curate --human for the compiled artifacts, and the origin: agent markers that record which specification items the agent proposed versus the human decided.

→ The full thesis, with before/after diagrams and the REAL vs VISION vs REJECTED table: uscha.dev/diamond · the mechanism, in three diagrams: uscha.dev/how


Documentation

  • uscha-kit/INSTALL.md — full install guide (npm, git, plugin)
  • uscha-kit/README.md — kit reference: configuration, every subcommand, the readiness KPI, the simplicity and rebuild gates
  • docs/ — the long deck, the operator's playbook, a skills reference and a one-pager (ES + EN)
  • docs/adr/INDEX.md — every architecture decision, grouped by who needs it, with a five-ADR reading order for a newcomer
  • docs/paper/ — the method written up as a paper

Each release ships a uscha-kit/CHANGELOG-X.Y.Z.md explaining what changed and why.

Developing Uscha itself

This repository is the source of the kit, and the method is applied to itself: it carries its own uscha.config.json, ACCEPTANCE.md and CONSTITUTION.md, and its readiness is measured by the same engine it ships.

uscha-kit/              # canonical source of the kit
  .claude/skills/       #   the 9 skills + qa_ledger.py (the engine)
  templates/            #   CLAUDE.md · CONSTITUTION.md · scripts · docs/adr
  tests/smoke-engine.sh #   the suite every engine change must pass
docs/                   # published artifacts (ES/EN twins) + the paper
audits/                 # adversarial audit outputs

The rules are in CLAUDE.md. The short version: no doc may claim what the engine does not do; the ES and EN twins travel together; every engine change carries a smoke test; and a PreToolUse hook stops the agent from writing a .approved golden. Scoped honestly: that hook is a best-effort guard and it is registered on the Claude target only — it inspects a tool call as TEXT, so an indirect write (a script that assembles the filename, a symlink) gets through, and every other target reports golden_guard: advisory. The MEASURED control is golden-diff, which compares bytes. A second hook, guard-pr-gate.py (2.12.0), keeps a pull request a draft while pr-gate reads red -- same scope, same honesty: Claude only, text only, and doctor reports pr_guard.

History

Born as a methodology for working with Claude Code, distilled with the Böckeler principle (computational blocks, inferential advises), and put through two adversarial audits (231 agents) that found the central principle inverted in the code — 1.3.0 flipped it right. The details are in audits/ and in the changelogs.

License

MIT — see LICENSE.

版本与发布记录

@andresmassello/uscha 共发布 76 个版本,首次发布于 2026/07/10;过去 12 个月发布了 76 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.14.1latest2026/11/053 天前
2.14.02026/11/053 天前
2.13.02026/11/025 天前
2.12.12026/11/026 天前
2.12.02026/11/026 天前
2.11.02026/11/016 天前

关于 @andresmassello/uscha 的常见问题

@andresmassello/uscha 是什么?

Spec-driven development for LLM coding agents: 9 skills + a stdlib evidence engine. Facts block, guesses advise; the human approves.

如何安装 @andresmassello/uscha?

在项目目录运行 npm install @andresmassello/uscha,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 uscha、uscha-kit,可以用 npx uscha 直接运行。

@andresmassello/uscha 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/andresmassello__uscha 是否存在。

@andresmassello/uscha 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@andresmassello/uscha 可以商用吗?

@andresmassello/uscha 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@andresmassello/uscha 的下载量有多少?

根据 npm 官方下载统计,@andresmassello/uscha 在 2026/10/06 – 2026/11/04 这 30 天内被下载 2,027 次,日均约 68 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@andresmassello/uscha 还在维护吗?

最新版本 2.14.1 发布于 2026/11/05(3 天前);至今共发布 76 个版本,其中过去 12 个月发布了 76 个;首次发布于 2026/07/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。