agentsclimarketplace

U drift analysis

Skill zig999/siegard-code/dist/.claude/skills/u-drift-analysis

Deterministic spec<->code drift analysis engine for /u-drift. Provides the stdlib scripts that build a spec inventory (spec_inventory.py), constrain the LLM-produced code inventory (validate_inventory.py), match the two by exact keys (match_drift.py), and render the report (render_report.py). Defines the matching keys, path normalization, severity/action tables, and the structural-vs-semantic scope boundary. Consumed by the /u-drift command and the u-drift-analyzer worker. Not user-invocable — callers run the scripts directly.From its SKILL.md

Install
npx -y skills add zig999/siegard-code --skill u-drift-analysis

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.3 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

u-drift-analysis

Engine skill for spec↔code drift analysis. All decision logic lives in stdlib scripts (P7/P11 — critical guarantees in testable code, not in prompts). The determinism boundary is explicit: everything here is byte-for-byte reproducible except the code-inventory extraction, which is produced by an LLM and clamped by validate_inventory.py (schema shape + physically-resolvable evidence).

scripts

ScriptProducer/ConsumerContract
spec_inventory.pyreads {SPECS_DIR} → writes spec-inventory.json (+ draft-skipped sidecar)schema u-shared-templates/spec-inventory.schema.yaml
validate_inventory.pyreads code-inventory.json + code_dir → pass/failfails closed unless shape-valid AND every file:line evidence resolves
match_drift.pyreads both inventories (+ skipped sidecar) → writes drift-report.jsonschema u-shared-templates/drift-report.schema.yaml
validate_findings.pyreads drift-verdicts.json + code_dir → pass/failRelease B — fails closed unless verdicts are shape-valid AND evidence resolves
merge_semantic.pyfolds validated drift-verdicts.json into drift-report.jsonRelease B — deterministic; relocates verdicts, re-numbers, recounts
render_report.pyreads drift-report.json → writes drift-report.mdpresentation only; no decisions
drift_common.pyshared helpers (normalization, ordering, counting)not a CLI

Exit codes are documented in each script's module docstring. spec_inventory.py returns 3 when no approved backend specs exist (caller maps to E_no_approved_specs); validate_inventory.py returns 1 on any violation.

Determinism boundary (plan R3)

StageProducerReproducible?
spec inventoryspec_inventory.pyYes — sorted domains/arrays/keys
code inventoryu-reverse-spec-analyzer (LLM)No — clamped by validate_inventory.py; invalid → 1 directed re-dispatch → still invalid = blocked
matchingmatch_drift.pyYes — byte-identical report from identical inventories
renderingrender_report.pyYes
semantic verdictu-drift-analyzer (Release B)Clamped by validate_findings.py; escape hatch undecidable, never a guess

Matching model

Every artifact class reduces to presence/absence of a canonical key. Within-item attribute drift (endpoint status codes, error HTTP status, state set, BR behavior) is NOT decided structurally — it is deferred to the semantic layer (Release B), because the code side is LLM-extracted and an attribute mismatch is as likely to be an extraction gap as real drift.

ArtifactKeyGranularity
endpoint{method} {normalized_path}endpoint
error_codecode stringcode
entityentity name (lowercased)entity; field-level diff when both sides present
state_machineentity name (lowercased)entity
eventevent nameevent
business_rulenone (no code-derivable key)semantic only — Release B

Verdicts:

  • spec-only key → missing_in_code — spec is the truth (SDD); create_implementation_cr
  • code-only key → missing_in_spec — document the code; update_spec
  • both present → aligned (structural)

Path normalization (plan R6)

normalize_path is single-side (no knowledge of the other inventory):

  1. drop query/fragment
  2. every path parameter segment → literal {param} (:id, {id}, <id> all collapse; names ignored so spec {id} matches code :userId)
  3. trailing slash removed; empty → /

base_path (router prefix) is stripped by the analyzer before emitting the code inventory. If a matched domain has spec endpoints AND code endpoints but zero keys intersect, match_drift.py emits ONE base_path_mismatch_suspected finding (undecidable, blocking, needs_human) instead of flooding the report — and never pairs unrelated endpoints heuristically.

Severity table

Statusendpointentity (item)entity.fieldstate_machineeventerror_code
missing_in_codeblockingmajorminormajormajorminor
missing_in_specmajormajorminorminorminorminor

Action table (direction of truth, plan R5)

Statusdefault_actionHandoff
missing_in_codecreate_implementation_cr/u-dev candidate
missing_in_spec (matched domain)update_spec/u-improve payload
undecidable / base_pathneeds_humanhuman triage (fix_spec + fix_code)

A code module with no matching spec domain and a spec domain with no matching code module are surfaced as skipped entries (no_spec_domain / no_code_module) with a suggested action — not per-artifact findings — to avoid flooding. create_spec and drifted remain in the schema for the semantic layer (Release B).

Scope

  • Backend only (openapi.yaml + *.back.md). Frontend feature-spec drift is out of scope for this release.
  • Approved specs only. Status: draft/review domains go to skipped with reason draft_status.
  • Release A populates missing_in_code / missing_in_spec / aligned for the five keyable classes. Release B adds business_rule matching, refines a subset of aligned endpoints to drifted, and introduces confirmed undecidable verdicts via u-drift-analyzer.

Dependencies

  • .claude/lib/minimal_yaml.py — OpenAPI parsing (stdlib loader)
  • u-shared-templates — the three schema/example pairs (spec-inventory, code-inventory, drift-report)
  • u-reverse-spec-analyzer (code-inventory mode) — produces code-inventory.json

What ships with it: 7 files

58.1 KB alongside SKILL.md, 7 of them executable

scripts/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.