Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

hegelhegel 搜索

Agent Skill

hegel 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

353

周安装

15

GitHub Stars

49

下载量

124
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:hegel(hegel 搜索)
来源仓库:https://github.com/hegeldev/hegel-skill
仓库路径:skills/hegel
安装命令:
npx skills add https://github.com/hegeldev/hegel-skill --skill hegel
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/hegeldev/hegel-skill --skill hegel

简介

hegel 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中快速定位候选结果。

  • 适用于关键词搜索、任务场景匹配或来源线索筛选等研究检索场景。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装并使用该技能。
  • 安装前需确认权限范围、维护状态,以及是否会触发联网或文件操作。
  • hegel 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Hegel: Property-Based Testing

Hegel is a family of property-based testing libraries supporting multiple languages, powered by Hypothesis. Tests integrate with standard language test runners. Hegel generates random inputs for your code and automatically shrinks failing cases to minimal counterexamples.

Even when PBTs add modest line coverage over unit tests, their value is in exercising combinations and boundary conditions that humans don't think to write by hand.

Code examples in this file use Python-like pseudocode to illustrate concepts. For exact API and syntax, load the language-specific reference (see step 1 of the workflow).

Workflow

Follow these steps when writing property-based tests.

1. Load the Language Reference

Determine the project language and load the corresponding reference from references/<language>/reference.md for API details and idiomatic patterns.

2. Explore the Code Under Test

Before writing any test, understand what you're testing:

  • Read the source code of the function/module under test
  • Read existing tests to understand expected behavior and edge cases
  • Read docstrings, comments, and type signatures for documented contracts
  • Read usage sites to see how callers use the code and what they expect

The goal is to find *evidence* for properties, not to invent them.

3. Identify Valuable Properties

Look for properties that are:

  • Grounded in evidence from the code, docs, or usage patterns
  • Non-trivial — they test real behavior, not tautologies, and do not duplicate the code being tested
  • Falsifiable — a buggy implementation could actually violate them

Write one test per property. Don't cram multiple properties into one test.

See the Property Catalogue below for a taxonomy of what to look for.

4. Check for Existing Tests to Evolve or Port

Before writing tests from scratch, check what already exists.

Existing PBTs in another framework (proptest, quickcheck, rapid, gopter, etc.) should be ported to hegel. Load the language-specific porting reference (references/<language>/porting.md). Key things to know about hegel when porting:

  • Hegel is imperative. Most PBT libraries declare what to generate in a function signature or strategy combinator. In hegel, your test receives a test case handle and calls tc.draw() whenever it needs a value — you can draw conditionally, in loops, and have later draws depend on earlier values without needing flat_map.
  • Shrinking is automatic. Hegel's shrinking is handled server-side by Hypothesis. You don't implement shrink logic or define shrinking strategies.
  • Standard assertions. Use the language's normal assertion mechanism. No special prop_assert! or return-a-bool pattern needed.
  • Broaden your generators. Many existing PBTs use narrow input ranges because shrinking was slow or unreliable. Hegel's shrinking is more robust — try broader generators than the originals.

Unit tests and example-based tests can often be evolved into PBTs. Tests with hardcoded seeds, parameterized examples, or multiple similar test cases are prime candidates. Load references/evolving-tests.md for detailed guidance on recognizing what property a unit test is hiding. If you can't immediately see the right property, start by parameterizing the test — replace concrete values with generated ones and keep a simple oracle. You can refine the property later.

Tests that use rand with fixed seeds are especially good candidates — the randomness should come from hegel instead so failures produce shrinkable counterexamples.

When you evolve an existing test, modify the existing test file rather than creating a new one. Property-based tests are tests like any other and belong with the code they're testing. Do not create a separate file for hegel tests.

5. Write the Tests

For each property:

  1. Add tests to the appropriate existing test file. Only create a new file if no relevant test file exists.
  2. Choose the simplest possible generators — see Generator Discipline below.
  3. Draw values, run the code under test, and assert the property.

6. Run and Reflect

Run the tests. When a test fails, ask:

  • Is this a real bug? If the code violates its own contract, flag the bug to the user and ask what to do, or fix the code if instructed to do so.
  • Is the property unsound? If you asserted something the code never promised, fix the test.
  • Is the generator too broad? Only if the failing input is genuinely outside the function's domain, add constraints. Investigate before constraining.

When NOT to Write PBTs

Property-based tests aren't always the right tool. Prefer unit tests when:

  • The test checks exact output. assert render(doc) == "<html>..." depends on a specific output format — there's no general property to check.
  • Complex setup dominates. Tests requiring database state, network mocks, or elaborate fixtures are hard to parameterize.
  • The test checks specific error messages. Exact error string checks are a unit test concern. PBTs are better for testing that errors are *raised*, not what they *say*.
  • No property is apparent. If you can't find a meaningful property after reading the code, don't force it. A good unit test beats a contrived PBT.

Property Catalogue

Use this catalogue to identify what to test. Not every category applies to every function — pick the ones supported by evidence from the code.

The first five patterns are ordered by how often they've found real bugs in practice.

Tier 1: High-Value Patterns

Model tests — For any data structure, the highest-value first test is a stateful model test: define rules for each operation (insert, remove, get, etc.), run them against both the library under test and a known-good reference (the "model"), and assert they agree after every operation. Use hegel's stateful testing support (see the language reference) rather than hand-rolling the operation loop.

The exact syntax varies significantly by language — check the language reference for the stateful testing API. Conceptually, a model test looks like:

state_machine MyMapTest:
    subject = MyMap()
    model = HashMap()

    rule insert():
        k = tc.draw(integers())
        v = tc.draw(integers())
        subject.insert(k, v)
        model.insert(k, v)

    rule remove():
        k = tc.draw(integers())
        subject.remove(k)
        model.remove(k)

    rule get():
        k = tc.draw(integers())
        assert subject.get(k) == model.get(k)

    invariant agrees:
        assert subject == model

Choose the right model: Vec for sequential containers, HashMap for hash maps, BTreeMap/sorted map for ordered maps, HashSet/set for unordered sets.

Idempotence tests — Any normalization, case conversion, or formatting function should satisfy f(f(x)) == f(x). Use full Unicode text generators (not ASCII-only) because Unicode edge cases like ß -> SS and combining characters are where bugs hide.

s = tc.draw(text())
once = normalize(s)
twice = normalize(once)
assert once == twice

Parse robustness — Parsers (from_str, parse, decode) should handle all input without panicking. The property is simple: it should never crash, even on garbage input.

s = tc.draw(text())
_ = MyType.parse(s)  # should return an error, never panic

Roundtrip testsparse(format(x)) == x for any serialize/deserialize pair. Test with the full input domain. Bugs hide at zero (scientific notation edge cases), large integers (precision loss through f64 for values > 2^53), and unusual string content.

n = tc.draw(integers())
s = format(n)
assert parse(s) == n

Boundary value tests — Integer boundary values (MIN, MAX, 0) are where overflow bugs hide. Don't add bounds to avoid them — they ARE the test. Negating MIN overflows, intermediate products overflow, GCD/LCM computations overflow on boundary inputs.

a = tc.draw(integers())  # includes MIN, MAX, 0
b = tc.draw(integers())
tc.assume(b != 0)
result = my_numeric_op(a, b)  # should not overflow/panic

Tier 2: General Property Categories

CategoryDescriptionExample
Commutativityorder of operations doesn't mattera + b == b + a or f(g(x)) == g(f(x))
Invariant preservationan operation maintains a structural propertyinsert into BST preserves ordering
Oracle / reference implcompare against a known-correct implementationmy_sort(xs) == std_sort(xs)
Monotonicitymore input means more (or equal) outputlen(xs ++ ys) >= len(xs)
Bounds / contractsoutput stays within documented limitsclamp(x, lo, hi) is in [lo, hi]
No-crash / robustnessfunction handles all valid inputs without panickingparse(arbitrary_string) doesn't crash
Equivalencetwo implementations produce the same resultiterative_fib(n) == recursive_fib(n)
Consistencyrelated APIs in the same library agreestring_width(s) == sum(char_width(c) for c in s)
Large input sizesexercise deep structure paths that small inputs missdraw size separately, force 50-200+ elements for trees/tries
Feature flag testingnon-default features are often less testedenable SIMD, nightly, or experimental features and run tests

Bug Patterns by Category

CategoryWhat to look for
Integer overflowBoundary values (MIN, MAX, 0) in arithmetic, GCD, negation, display
Idempotence failureCase conversion / normalization with Unicode (ß -> SS), word splitting on case transitions
Precision lossNumbers routed through f64 lose precision for integers > 2^53
Roundtrip failureFormat/parse on edge cases: zero, empty strings, unusual path components
Parse panicfrom_str delegates to a constructor that panics instead of returning Err
Stale stateUpdate operations that modify one index but don't clean up the old entry in another
Unicode line breaks\u{85} (NEL), \u{2028} (LS), \u{2029} (PS) treated inconsistently as line breaks
SIMD divergenceSIMD code path produces different results than the scalar fallback
Deep structure bugsTraversal that only fails when data structure has multiple internal levels (50-200+ elements)

Choosing Properties

Properties must be evidence-based. Find evidence in:

  • Names and type signatures: A function merge(a: List, b: List) -> List implies the output length might equal the sum of input lengths.
  • Docstrings and comments: "Returns a sorted list" directly gives you an invariant.
  • Assertions and debug checks in the source: These are properties the author already identified — they may suggest other invariants.
  • Usage patterns: If callers always assume a result is non-empty, assert that.
  • Existing tests: Unit tests often encode specific instances of general properties.

Err on the side of creating more properties rather than fewer, and if they fail investigate whether the failure is legitimate behavior or not.

Beware of properties that seem universal but aren't. Read the docs carefully before asserting a property. Examples from real testing:

  • Grapheme-based string reverse is NOT an involution (reverse(reverse("\n\r"))!= "\n\r" because \r\n is one grapheme cluster while \n\r is two).
  • A method called difference might mean symmetric difference (A triangle B), not set difference (A \ B) — check the docs.
  • A function documented as "returns the largest key <= k" means <=, not <.

When a property fails, investigate whether it's a real bug or a genuine edge case in the domain. A weaker property often still holds.

Generator Discipline

The most common mistake when writing property-based tests is over-constraining generators. Broad generators find more bugs because they explore inputs the developer didn't anticipate. Constrained generators give a false sense of safety.

Start With No Bounds

If the function accepts any integer, generate any integer:

n = tc.draw(integers())  # full range of the type, no min/max

Preemptively adding bounds like .min(0).max(100) means you'll never discover that the function overflows on large values, mishandles negatives, or breaks at the type's boundaries. Those are exactly the bugs PBT is designed to find.

Edge Cases Are the Point

Don't narrow ranges to "avoid edge cases." If a function claims to work on all integers, test it on all integers — including MIN, MAX, 0, -1, and 1. If it breaks, that's valuable information.

Don't Require Non-Empty by Default

Unless the function's contract explicitly requires non-empty input, test with empty collections too. If a function panics on an empty collection, that might be a bug worth knowing about.

When a Test Fails on Extreme Values

Assume it's a real bug unless you have strong evidence otherwise. If in doubt, ask the user.

  • If the function's documentation says it handles all integers but it overflows on MAX, that's a bug in the code, not in your test.
  • Only add bounds after investigating and confirming the input is outside the function's documented domain.

When to Add Constraints

Add generator bounds only when:

  1. The function's contract explicitly excludes some inputs. For example, a square root function documents that input must be >= 0.
  2. You need to avoid undefined behavior. For example, division by zero.
  3. A test failure has been investigated and confirmed to be outside the function's domain.

Avoid Rejection Sampling Where Possible

When a constraint involves relationships between multiple generated values, you might use tc.assume():

a = tc.draw(integers())
b = tc.draw(integers())
tc.assume(a != b)  # this is fine for simple constraints

But it's better to construct valid inputs directly when you can:

# Instead of tc.assume(a <= b), generate in order:
a = tc.draw(integers())
b = tc.draw(integers())
if a > b:
    a, b = b, a

This is particularly important when the rejection rate would be high. For example, integers().map(n -> n * 2) is much better than integers().filter(n -> n % 2 == 0) — the latter throws away ~50% of test cases.

Getting Large Collections

Hegel's default collection size is small. If you need large collections (e.g., to exercise deep tree paths or multi-level node structures), draw the size separately:

# can generate large collections, and hegel can shrink n to find the minimal size
n = tc.draw(integers(min=0, max=300))
keys = tc.draw(lists(integers(), min_size=n))  # no max_size — let hegel go bigger

# BAD — hegel's default size distribution rarely produces 100+ elements
keys = tc.draw(lists(integers()))

Use Unique Element Generation for Key Generation

When testing maps/sets that need unique keys, use the unique option on collection generators. This avoids confusion about which value wins for duplicate keys. See the language-specific reference for syntax.

Handling Randomness in Code Under Test

When the code under test requires an RNG, do not create a seeded RNG with a hegel-generated seed. Hegel can only shrink the seed integer, not the actual random decisions the RNG makes — so when a test fails, you get a meaningless minimal seed rather than a meaningful minimal sequence of random choices.

Instead, use hegel's random generator, which gives you an RNG that routes random decisions through hegel's shrinking engine. See the language-specific reference for the exact API.

Two modes: artificial vs true randomness

  • Default (artificial randomness): Every random decision goes through hegel, enabling fine-grained shrinking of individual random values. Best for most code.
  • True randomness mode: Generates a single seed via hegel, then creates a real RNG from it. Hegel can only shrink the seed, not individual random decisions. Use this when the code under test does rejection sampling or otherwise depends on the RNG producing statistically random-looking output — artificial randomness can cause rejection loops to hang.

How to choose: Start with the default. If tests hang or time out because the code does rejection sampling internally, switch to true randomness mode.

Refactoring concrete RNG types

If the code under test takes a concrete RNG type rather than a trait/interface, consider whether it should be refactored to accept a generic RNG. This is both better API design and makes the code testable with hegel's random generator. Suggest this refactoring to the user.

Common Mistakes

  1. Over-constraining generators — Adding bounds "just in case" means the test will never find bugs at boundary values or with unexpected inputs. The whole value of PBT is exploring the input space the developer didn't think to test by hand. See Generator Discipline above.
  2. Testing trivial propertiesassert x == x or assert len(vec) >= 0 test nothing useful. Every property should be falsifiable by a buggy implementation.
  3. Using the implementation as the oracle — If your test calls the same function to compute the expected result, it can never fail. Use an independent reference implementation, a simpler algorithm, or a structural property.
  4. High rejection rates — If .filter() or tc.assume() rejects most inputs, hegel will give up. Restructure generators to produce valid inputs directly (use .map() or dependent draws).
  5. Creating a separate test file for hegel tests — Property-based tests belong alongside the existing tests for the same code. Add them to existing test files.
  6. Using manually seeded RNGs — Use hegel's random generator so hegel controls the random decisions and can shrink them individually. See "Handling Randomness" above.
  7. Overflowing in test code — When computing values from generated data (e.g., map.insert(k, k * 10)), your test code itself can overflow before the library has a chance to be buggy. Use wrapping arithmetic or draw a smaller type and widen it to prevent overflow in the test. Distinguish "this constraint protects the library's contract" (keep it) from "this constraint prevents my test from overflowing" (use wrapping arithmetic instead).
  8. Restricting collection size for performance — If a test is slow with large collections, lower the test case count rather than restricting the input space. A slow test that finds bugs beats a fast test that can't. Many tree/trie bugs only manifest at 50-200+ elements.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.03%
按下载量换算42

Claude

31.09%
按下载量换算39

Cursor

18.45%
按下载量换算23

Gemini CLI

8.39%
按下载量换算10

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills