blockwatch-cli 0.12.0__tar.gz → 0.14.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/AGENTS.md +16 -7
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/CHANGELOG.md +45 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/CLAUDE.md +16 -7
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/Cargo.lock +1 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/Cargo.toml +1 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/PKG-INFO +1 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/README.md +4 -4
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/blockwatch.toml +13 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/ci.md +2 -2
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/cli.md +3 -3
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/symbols.md +49 -5
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/README.md +2 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/same-as.md +79 -16
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/setup.py +1 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/blocks.rs +3 -2
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/json.rs +1 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/markdown.rs +428 -2
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/mdx.rs +45 -3
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/mod.rs +3 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/toml.rs +1 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/yaml.rs +1 -1
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/skill.md +26 -25
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/symbol_path.rs +30 -7
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/symbols.rs +9 -8
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/same_as.rs +623 -102
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/virtual_blocks.rs +38 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/skill.rs +3 -3
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/symbol_references.rs +21 -0
- blockwatch_cli-0.14.0/tests/testdata/symbol_references/markdown_source.rs +3 -0
- blockwatch_cli-0.14.0/tests/testdata/symbol_references/markdown_target.markdown +5 -0
- blockwatch_cli-0.14.0/tests/testdata/symbol_references/md_source.rs +3 -0
- blockwatch_cli-0.14.0/tests/testdata/symbol_references/md_target.md +5 -0
- blockwatch_cli-0.14.0/tests/testdata/symbol_references/mdx_source.rs +3 -0
- blockwatch_cli-0.14.0/tests/testdata/symbol_references/mdx_target.mdx +5 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.agents/.claude-plugin/plugin.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.agents/skills/blockwatch/SKILL.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.claude-plugin/marketplace.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/dependabot.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/workflows/blockwatch.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/workflows/codeql.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/workflows/markdownlint.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/workflows/pypi.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/workflows/release.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/workflows/rust.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.github/workflows/trusted-checks.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.gitignore +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.markdownlint-cli2.yaml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.pre-commit-config.yaml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/.pre-commit-hooks.yaml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/LICENSE +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/SECURITY.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/clippy.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/codecov.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/demo.gif +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/dist-workspace.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/agents.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/affects.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/check-ai.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/check-lua.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/keep-sorted.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/keep-unique.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/line-count.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/docs/validators/line-pattern.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/pypi/pyproject.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/pyproject.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/release.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/scripts/check_language_count.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/scripts/check_latest_gpt_nano_model.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/block_parser.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/cli.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/config.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/diff_parser.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/flags.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/fs.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/bash.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/c.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/c_sharp.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/cmake.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/cpp.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/css.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/dart.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/dockerfile.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/elixir.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/go.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/graphql.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/groovy.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/hcl.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/html.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/java.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/javascript.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/json.scm +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/kotlin.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/lean.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/lua.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/makefile.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/nix.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/ocaml.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/php.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/proto.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/python.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/ruby.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/rust.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/scala.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/sql.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/starlark.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/swift.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/tsx.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/typescript.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/language_parsers/xml.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/lib.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/main.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/path_arguments.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/paths_glob.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/repo_path.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/report.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/sarif.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/settings.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/tag_parser.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/affects.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/check_ai.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/check_lua.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/keep_sorted.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/keep_unique.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/line_count.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/line_pattern.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/validators/mod.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/src/violation_address.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/affects.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/check_ai.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/check_lua.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/common/empty.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/common/mod.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/config.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/encoding.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/general.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/keep_sorted.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/keep_unique.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/line_count.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/line_pattern.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/list.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/path_arguments.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/repository_root.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/same_as.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/sarif.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/suppressions.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/cross_file_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/cross_file_target.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/custom_ext_source.javascript +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/custom_ext_target.javascript +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/dangling.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/missing_symbol.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/more_added_than_deleted.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/multiline_tag_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/multiline_tag_target.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/nested_mapping_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/nested_mapping_target.yaml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/sibling.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/symbol_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/symbol_target.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/table_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/table_target.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/tag_and_content_source.ts +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/tag_and_content_target.ts +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/whole_file_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/affects/whole_file_target.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_ai/two_blocks.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/affects.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/affects.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/affects_drift.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/blocking_io.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/blocking_io.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/echo.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/fail.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/mode.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/os.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/pathfmt/report_path.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/pathfmt/source.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/pattern.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/pattern_many_matches.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/pattern_no_match.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/success.lua +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/check_lua/success_and_failure.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/config/glob_target/config.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/config/glob_target/package.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/config/glob_target/plugins/blue/package.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/config/glob_target/plugins/green/package.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/config/glob_target/plugins/red/package.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/block_selection.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/custom_file_extension.javascript +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/custom_file_extension.python +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/disable_enable.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/paths/invalid.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/paths/subdir/nested_invalid.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/paths/valid.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/general/severity.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/hidden/.github/workflows/ci.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/keep_sorted/orderings.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/keep_unique/basic_and_pattern.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/line_count/equality_and_greater_than.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/line_pattern/forbidden_text.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/line_pattern/hex_and_word_patterns.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/list/.hg/.gitkeep +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/list/a.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/list/b.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/positions/unicode_columns.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/custom_ext_source.javascript +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/custom_ext_target.javascript +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/package.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/paths/alpha/item.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/paths/beta/item.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/paths_and_block_source.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/paths_source.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/sibling.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/split_table_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/split_table_target.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/symbol_mismatch_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/symbol_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/target.md +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/whole_file_mismatch_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/whole_file_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/same_as/whole_file_target.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/sarif/advisory.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/sarif/clean.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/sarif/sorted.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/sarif/unnamed.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/commit_msg.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/commit_msg_gone_a.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/commit_msg_gone_b.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/commit_msg_lowercase_trailer.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/commit_msg_malformed.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/commit_msg_with_noise.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/dangling.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/sorted.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/symbol.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/symbol_target.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/two_rules.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/suppressions/unnamed.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/escapes_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/escapes_target.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/filter_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/filter_target.yaml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/json_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/json_target.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/jsonc_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/jsonc_target.jsonc +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/mixed_list_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/mixed_list_target.json +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/toml_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/toml_target.toml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/yaml_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/yaml_target.yaml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/yml_source.rs +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/symbol_references/yml_target.yml +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/affects/pair.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/clean/counted.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/clean/noop.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/clean/notes.txt +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/clean/sorted.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/diff/two_blocks.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/failing/unsorted.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/testdata/verbosity/mixed/both_kinds.py +0 -0
- {blockwatch_cli-0.12.0 → blockwatch_cli-0.14.0}/tests/verbosity.rs +0 -0
|
@@ -62,7 +62,10 @@ For example:
|
|
|
62
62
|
- *Prefer* the harness's editing tools to one-off scripts.
|
|
63
63
|
- *Always* handle the variants of an enum with an exhaustive `match`. A `let ... else`, or an `if` that handles one
|
|
64
64
|
variant and sends the rest to a single branch, quietly gives any new variant whatever that branch does. With a
|
|
65
|
-
`match`, the compiler makes you decide what to do with each new variant.
|
|
65
|
+
`match`, the compiler makes you decide what to do with each new variant. One exception: a `match` on another
|
|
66
|
+
crate's enum can end with `_` when it only asks whether a value is one variant, and no new variant could be that
|
|
67
|
+
one. For example, every Markdown heading is `mdast::Node::Heading`, so the other node types can go to `_ => None`.
|
|
68
|
+
Say why in a comment next to the `_`.
|
|
66
69
|
- *Always* give an item the narrowest visibility that compiles: private, then `pub(super)`, then `pub(crate)`.
|
|
67
70
|
blockwatch is a program, not a library. Only `run` and `count_rust_blocks` in `lib.rs` are `pub`, for `main.rs` and
|
|
68
71
|
the fuzz target. The `unreachable_pub` lint makes `cargo clippy -- -D warnings` fail on any other `pub`.
|
|
@@ -200,8 +203,9 @@ The main modules:
|
|
|
200
203
|
- `src/virtual_blocks.rs` — `VirtualBlock`, a block that the config file declares in one file, instead of tags in a
|
|
201
204
|
comment. A file that can't or must not hold a tag, such as `package.json` or a prompt, can only get blocks this way.
|
|
202
205
|
It is a block of the file it wraps. Its `Locator` says how to find it:
|
|
203
|
-
- `Symbol`: the content is what a reference to the symbol reads:
|
|
204
|
-
|
|
206
|
+
- `Symbol`: the content is what a reference to the symbol reads: its value, or else the definition's text. A value
|
|
207
|
+
written as is, such as a number or a Markdown section, keeps its place in the file. A value with quotes or escapes
|
|
208
|
+
is decoded (`ContentText::Decoded`), so every line of it reports the value's start.
|
|
205
209
|
- `Pattern`: the `target-pattern` regex must match once. The content is its `value` group, or else the whole match.
|
|
206
210
|
- `File`: the content is the whole file.
|
|
207
211
|
|
|
@@ -224,6 +228,8 @@ The main modules:
|
|
|
224
228
|
syntax tree is nested.
|
|
225
229
|
- YAML walks its syntax tree itself. An alias has a position in a sequence but can't be addressed, and a query can't
|
|
226
230
|
express that.
|
|
231
|
+
- Markdown finds its sections with the `markdown` crate. The `section` nodes of `tree-sitter-md` don't end at a
|
|
232
|
+
heading underlined with `---`.
|
|
227
233
|
|
|
228
234
|
Each language's tests list every symbol it finds. When you give a language symbols, also document its paths in
|
|
229
235
|
`docs/symbols.md` and in the "Symbols" section of the skill, `src/skill.md`. A test in `language_parsers/mod.rs` and the
|
|
@@ -269,8 +275,11 @@ skill this project ships, so that agents can add blocks to **other** repositorie
|
|
|
269
275
|
They are not instructions for working on blockwatch, and changing them changes what users get. This file is the
|
|
270
276
|
guidance for working on blockwatch.
|
|
271
277
|
|
|
272
|
-
|
|
273
|
-
|
|
278
|
+
`src/skill.md` must not hold block tags. A project that saves the skill parses it too, so each tag would become a block
|
|
279
|
+
in that project. To point a block at a section of the skill, use the section's headings, such as
|
|
280
|
+
`src/skill.md#/blockwatch/Symbols/JSON`. To point at only a part of a section, give that part a heading of its own.
|
|
281
|
+
When the section needs a rule of its own, such as a `same-as-pattern`, add a `[[block]]` entry for it to
|
|
282
|
+
`blockwatch.toml`, next to the others for `src/skill.md`.
|
|
274
283
|
|
|
275
284
|
Each agent's local config directory is left out of git on purpose: `.claude/`, `.cursor/`, `.gemini/`, `.windsurf/`,
|
|
276
285
|
`.aider*`, and the others listed in `.gitignore`. Don't commit agent-specific settings. Anything a future contributor
|
|
@@ -279,8 +288,8 @@ needs belongs in this file.
|
|
|
279
288
|
## Release
|
|
280
289
|
|
|
281
290
|
The GitHub Actions workflows in `.github/workflows/` build releases with `cargo-dist`, configured in
|
|
282
|
-
`dist-workspace.toml`.
|
|
283
|
-
|
|
291
|
+
`dist-workspace.toml`. `cargo release` bumps the version in `Cargo.toml`, in a commit titled `chore: Release`, and
|
|
292
|
+
tags that commit `vX.Y.Z`.
|
|
284
293
|
|
|
285
294
|
`pypi.yml` builds the same tag for PyPI, as `blockwatch-cli`. The pre-commit hooks install that package through the
|
|
286
295
|
root `setup.py`. So if the upload for a tag fails, the hooks at that tag can't install.
|
|
@@ -12,6 +12,51 @@ Releases up to and including v0.3.11 predate this file. Their notes live on the
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased] - ReleaseDate
|
|
14
14
|
|
|
15
|
+
## [0.14.0] - 2026-10-16
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `same-as-pattern` can compare a key with its value. Every named group, such as `(?P<code>\d+)` and
|
|
20
|
+
`(?P<message>.+)`, takes part, and each match is one record. So a message that moves to another code fails, even
|
|
21
|
+
though the messages alone still agree. Both patterns need the same groups. Each group can have its own
|
|
22
|
+
`same-as-format`, such as `name:identifier,value:numeric`. See
|
|
23
|
+
[Compare several groups](docs/validators/same-as.md#compare-several-groups) and
|
|
24
|
+
[A format for each group](docs/validators/same-as.md#a-format-for-each-group)
|
|
25
|
+
([#99](https://github.com/mennanov/blockwatch/issues/99)).
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- A `same-as-pattern` with named groups other than `value` now compares them too. Before, only `value` counted, or the
|
|
30
|
+
whole match when the pattern had no `value` group. To keep comparing only `value`, change the other groups to
|
|
31
|
+
`(?:…)`.
|
|
32
|
+
- An error about the `same-as-mode`, `same-as-format` or `same-as-pattern` of a block with `same-as` or
|
|
33
|
+
`same-as-paths` now shows the block, such as `invalid same-as attributes on block src/config.rs:limits at line 3`.
|
|
34
|
+
Before, it showed only the bad value.
|
|
35
|
+
|
|
36
|
+
## [0.13.0] - 2026-10-15
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- A symbol path can point at a section of a Markdown file (`.md`, `.markdown`, `.mdx`) by its headings. For example,
|
|
41
|
+
`docs/cli.md#/CLI Reference/Run Modes` is the `## Run Modes` section under the `# CLI Reference` title. So
|
|
42
|
+
`affects` and `same-as` can point at a section, and a `[[block]]` entry can wrap one, with no tags in the file. See
|
|
43
|
+
[Markdown](docs/symbols.md#markdown) ([#175](https://github.com/mennanov/blockwatch/issues/175)).
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- Messages now show a space inside a key of a symbol path as written. Markdown headings almost always hold spaces, so
|
|
48
|
+
a path to a section reads like the file: `docs/cli.md#/CLI Reference/Run Modes`, not
|
|
49
|
+
`docs/cli.md#/CLI%20Reference/Run%20Modes`. A space at the start or end of a key still shows as `%20`. In any file,
|
|
50
|
+
an `affects` or `same-as` violation on a key with a space gets a new hash, so update any `--suppress` address with
|
|
51
|
+
four parts that points at it.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- The skill that `blockwatch skill` prints no longer adds blocks to the project that saves it. Before, a saved skill
|
|
56
|
+
added six named blocks, such as `validator-catalog` and `json-paths`, to `blockwatch list` and to the
|
|
57
|
+
`--verbosity summary` counts. Save the skill again with `blockwatch skill` to remove them
|
|
58
|
+
([#174](https://github.com/mennanov/blockwatch/issues/174)).
|
|
59
|
+
|
|
15
60
|
## [0.12.0] - 2026-10-15
|
|
16
61
|
|
|
17
62
|
### Changed
|
|
@@ -62,7 +62,10 @@ For example:
|
|
|
62
62
|
- *Prefer* the harness's editing tools to one-off scripts.
|
|
63
63
|
- *Always* handle the variants of an enum with an exhaustive `match`. A `let ... else`, or an `if` that handles one
|
|
64
64
|
variant and sends the rest to a single branch, quietly gives any new variant whatever that branch does. With a
|
|
65
|
-
`match`, the compiler makes you decide what to do with each new variant.
|
|
65
|
+
`match`, the compiler makes you decide what to do with each new variant. One exception: a `match` on another
|
|
66
|
+
crate's enum can end with `_` when it only asks whether a value is one variant, and no new variant could be that
|
|
67
|
+
one. For example, every Markdown heading is `mdast::Node::Heading`, so the other node types can go to `_ => None`.
|
|
68
|
+
Say why in a comment next to the `_`.
|
|
66
69
|
- *Always* give an item the narrowest visibility that compiles: private, then `pub(super)`, then `pub(crate)`.
|
|
67
70
|
blockwatch is a program, not a library. Only `run` and `count_rust_blocks` in `lib.rs` are `pub`, for `main.rs` and
|
|
68
71
|
the fuzz target. The `unreachable_pub` lint makes `cargo clippy -- -D warnings` fail on any other `pub`.
|
|
@@ -200,8 +203,9 @@ The main modules:
|
|
|
200
203
|
- `src/virtual_blocks.rs` — `VirtualBlock`, a block that the config file declares in one file, instead of tags in a
|
|
201
204
|
comment. A file that can't or must not hold a tag, such as `package.json` or a prompt, can only get blocks this way.
|
|
202
205
|
It is a block of the file it wraps. Its `Locator` says how to find it:
|
|
203
|
-
- `Symbol`: the content is what a reference to the symbol reads:
|
|
204
|
-
|
|
206
|
+
- `Symbol`: the content is what a reference to the symbol reads: its value, or else the definition's text. A value
|
|
207
|
+
written as is, such as a number or a Markdown section, keeps its place in the file. A value with quotes or escapes
|
|
208
|
+
is decoded (`ContentText::Decoded`), so every line of it reports the value's start.
|
|
205
209
|
- `Pattern`: the `target-pattern` regex must match once. The content is its `value` group, or else the whole match.
|
|
206
210
|
- `File`: the content is the whole file.
|
|
207
211
|
|
|
@@ -224,6 +228,8 @@ The main modules:
|
|
|
224
228
|
syntax tree is nested.
|
|
225
229
|
- YAML walks its syntax tree itself. An alias has a position in a sequence but can't be addressed, and a query can't
|
|
226
230
|
express that.
|
|
231
|
+
- Markdown finds its sections with the `markdown` crate. The `section` nodes of `tree-sitter-md` don't end at a
|
|
232
|
+
heading underlined with `---`.
|
|
227
233
|
|
|
228
234
|
Each language's tests list every symbol it finds. When you give a language symbols, also document its paths in
|
|
229
235
|
`docs/symbols.md` and in the "Symbols" section of the skill, `src/skill.md`. A test in `language_parsers/mod.rs` and the
|
|
@@ -269,8 +275,11 @@ skill this project ships, so that agents can add blocks to **other** repositorie
|
|
|
269
275
|
They are not instructions for working on blockwatch, and changing them changes what users get. This file is the
|
|
270
276
|
guidance for working on blockwatch.
|
|
271
277
|
|
|
272
|
-
|
|
273
|
-
|
|
278
|
+
`src/skill.md` must not hold block tags. A project that saves the skill parses it too, so each tag would become a block
|
|
279
|
+
in that project. To point a block at a section of the skill, use the section's headings, such as
|
|
280
|
+
`src/skill.md#/blockwatch/Symbols/JSON`. To point at only a part of a section, give that part a heading of its own.
|
|
281
|
+
When the section needs a rule of its own, such as a `same-as-pattern`, add a `[[block]]` entry for it to
|
|
282
|
+
`blockwatch.toml`, next to the others for `src/skill.md`.
|
|
274
283
|
|
|
275
284
|
Each agent's local config directory is left out of git on purpose: `.claude/`, `.cursor/`, `.gemini/`, `.windsurf/`,
|
|
276
285
|
`.aider*`, and the others listed in `.gitignore`. Don't commit agent-specific settings. Anything a future contributor
|
|
@@ -279,8 +288,8 @@ needs belongs in this file.
|
|
|
279
288
|
## Release
|
|
280
289
|
|
|
281
290
|
The GitHub Actions workflows in `.github/workflows/` build releases with `cargo-dist`, configured in
|
|
282
|
-
`dist-workspace.toml`.
|
|
283
|
-
|
|
291
|
+
`dist-workspace.toml`. `cargo release` bumps the version in `Cargo.toml`, in a commit titled `chore: Release`, and
|
|
292
|
+
tags that commit `vX.Y.Z`.
|
|
284
293
|
|
|
285
294
|
`pypi.yml` builds the same tag for PyPI, as `blockwatch-cli`. The pre-commit hooks install that package through the
|
|
286
295
|
root `setup.py`. So if the upload for a tag fails, the hooks at that tag can't install.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blockwatch-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: Language agnostic linter that keeps your code and documentation in sync and valid
|
|
5
5
|
Keywords: linter,sync,drift,comments,agents
|
|
6
6
|
Home-Page: https://github.com/mennanov/blockwatch
|
|
@@ -88,9 +88,9 @@ Two validators work across files:
|
|
|
88
88
|
- `affects` fails when a diff touches a block without also changing what it points to.
|
|
89
89
|
- `same-as` fails when a block and its target hold different values. It needs no diff.
|
|
90
90
|
|
|
91
|
-
Both can point to a block, a whole file,
|
|
92
|
-
(see [Symbols](docs/symbols.md)). The other validators check a single block on their own: the things
|
|
93
|
-
have to nitpick in code review.
|
|
91
|
+
Both can point to a block, a whole file, a specific value in a file like `package.json#/version`, or a section of a
|
|
92
|
+
Markdown file (see [Symbols](docs/symbols.md)). The other validators check a single block on their own: the things
|
|
93
|
+
you'd otherwise have to nitpick in code review.
|
|
94
94
|
|
|
95
95
|
<!-- <block name="available-validators"
|
|
96
96
|
same-as="src/validators/mod.rs:validator-registry, docs/validators/README.md:validators-index"
|
|
@@ -214,7 +214,7 @@ exclusions, and custom extension mappings.
|
|
|
214
214
|
|
|
215
215
|
```yaml
|
|
216
216
|
- repo: https://github.com/mennanov/blockwatch
|
|
217
|
-
rev: v0.
|
|
217
|
+
rev: v0.14.0 # Use latest release
|
|
218
218
|
hooks:
|
|
219
219
|
- id: blockwatch
|
|
220
220
|
```
|
|
@@ -38,3 +38,16 @@ same-as = '''.github/workflows/codeql.yml,
|
|
|
38
38
|
.github/workflows/pypi.yml,
|
|
39
39
|
.github/workflows/rust.yml'''
|
|
40
40
|
same-as-pattern = '(?:actions/checkout@|^)(?P<value>v\d+)$'
|
|
41
|
+
|
|
42
|
+
# `blockwatch skill` prints src/skill.md, and projects save that output. A tag in that file would become a block in
|
|
43
|
+
# every one of those projects. So blocks point at its sections by their headings, and these entries hold the pattern
|
|
44
|
+
# that reads a section, which the section can't hold itself.
|
|
45
|
+
[[block]]
|
|
46
|
+
target = 'src/skill.md#/blockwatch/Validator reference'
|
|
47
|
+
name = 'validator-reference'
|
|
48
|
+
same-as-pattern = '^\|\s*`(?P<value>[a-z-]+)`'
|
|
49
|
+
|
|
50
|
+
[[block]]
|
|
51
|
+
target = 'src/skill.md#/blockwatch/Symbols/Files with symbols'
|
|
52
|
+
name = 'extensions-with-symbols'
|
|
53
|
+
same-as-pattern = '`\.?(?P<value>[A-Za-z]+)`'
|
|
@@ -19,7 +19,7 @@ To use [pre-commit](https://pre-commit.com), add the hook to `.pre-commit-config
|
|
|
19
19
|
|
|
20
20
|
```yaml
|
|
21
21
|
- repo: https://github.com/mennanov/blockwatch
|
|
22
|
-
rev: v0.
|
|
22
|
+
rev: v0.14.0 # Use latest release
|
|
23
23
|
hooks:
|
|
24
24
|
- id: blockwatch
|
|
25
25
|
```
|
|
@@ -59,7 +59,7 @@ The `blockwatch` hook runs before the commit message exists, so it cannot see a
|
|
|
59
59
|
|
|
60
60
|
```yaml
|
|
61
61
|
- repo: https://github.com/mennanov/blockwatch
|
|
62
|
-
rev: v0.
|
|
62
|
+
rev: v0.14.0 # Use latest release
|
|
63
63
|
hooks:
|
|
64
64
|
- id: blockwatch-commit-msg
|
|
65
65
|
```
|
|
@@ -555,15 +555,15 @@ Nothing else about the run changes: the same violations are found, and the exit
|
|
|
555
555
|
"tool": {
|
|
556
556
|
"driver": {
|
|
557
557
|
"name": "blockwatch",
|
|
558
|
-
"version": "0.
|
|
559
|
-
"semanticVersion": "0.
|
|
558
|
+
"version": "0.14.0",
|
|
559
|
+
"semanticVersion": "0.14.0",
|
|
560
560
|
"informationUri": "https://github.com/mennanov/blockwatch",
|
|
561
561
|
"rules": [
|
|
562
562
|
{
|
|
563
563
|
"id": "keep-sorted",
|
|
564
564
|
"name": "keep-sorted",
|
|
565
565
|
"shortDescription": { "text": "Requires the lines of a block to stay in order." },
|
|
566
|
-
"helpUri": "https://github.com/mennanov/blockwatch/blob/v0.
|
|
566
|
+
"helpUri": "https://github.com/mennanov/blockwatch/blob/v0.14.0/docs/validators/keep-sorted.md"
|
|
567
567
|
}
|
|
568
568
|
]
|
|
569
569
|
}
|
|
@@ -24,11 +24,12 @@ declares, instead of tags in a comment.
|
|
|
24
24
|
<!-- <block name="extensions-with-symbols" same-as="src/language_parsers/mod.rs:extensions-with-symbols"
|
|
25
25
|
same-as-pattern="`\.?(?P<value>[A-Za-z]+)`"> -->
|
|
26
26
|
|
|
27
|
-
| Language | Files | Paths
|
|
28
|
-
|
|
29
|
-
| JSON | `.json`, `.jsonc`, `.webmanifest` | [JSON](#json)
|
|
30
|
-
| TOML | `.toml`, `Pipfile` | [TOML](#toml)
|
|
31
|
-
| YAML | `.yaml`, `.yml`, `.cff` | [YAML](#yaml)
|
|
27
|
+
| Language | Files | Paths |
|
|
28
|
+
|----------|-----------------------------------|-----------------------|
|
|
29
|
+
| JSON | `.json`, `.jsonc`, `.webmanifest` | [JSON](#json) |
|
|
30
|
+
| TOML | `.toml`, `Pipfile` | [TOML](#toml) |
|
|
31
|
+
| YAML | `.yaml`, `.yml`, `.cff` | [YAML](#yaml) |
|
|
32
|
+
| Markdown | `.md`, `.markdown`, `.mdx` | [Markdown](#markdown) |
|
|
32
33
|
|
|
33
34
|
<!-- </block> -->
|
|
34
35
|
|
|
@@ -189,6 +190,49 @@ jobs:
|
|
|
189
190
|
|
|
190
191
|
<!-- </block> -->
|
|
191
192
|
|
|
193
|
+
## Markdown
|
|
194
|
+
|
|
195
|
+
<!-- <block name="markdown-paths"> -->
|
|
196
|
+
|
|
197
|
+
Every section is a symbol. A section is a heading and everything up to the next heading of the same or a higher level.
|
|
198
|
+
Its path is the text of each heading it is under, then its own:
|
|
199
|
+
|
|
200
|
+
```markdown
|
|
201
|
+
# Guide
|
|
202
|
+
|
|
203
|
+
## Install
|
|
204
|
+
|
|
205
|
+
Run `cargo install blockwatch`.
|
|
206
|
+
|
|
207
|
+
### From source
|
|
208
|
+
|
|
209
|
+
Clone the repository.
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
| Path | Points at |
|
|
213
|
+
|-------------------------------|---------------------------------------------|
|
|
214
|
+
| `#/Guide` | everything below `# Guide` |
|
|
215
|
+
| `#/Guide/Install` | `Run …` and the whole `From source` section |
|
|
216
|
+
| `#/Guide/Install/From source` | `Clone the repository.` |
|
|
217
|
+
|
|
218
|
+
- **The top `#` title is part of every path**, as above.
|
|
219
|
+
- **A section holds its subsections.** `affects` counts a change to any of its lines, the heading included.
|
|
220
|
+
- **A section's value is its text without the heading line.** `same-as` compares that text. The blank lines around it
|
|
221
|
+
don't count.
|
|
222
|
+
- **A heading counts as a reader sees it.** ``## The `--diff` flag`` is `#/The --diff flag`. Code, emphasis and links
|
|
223
|
+
lose their markup.
|
|
224
|
+
- **Headings underlined with `===` or `---` count.** A `#` line in a code block doesn't. Neither does a heading in a
|
|
225
|
+
quote, a list item or an HTML block.
|
|
226
|
+
- **The same heading twice under one parent is a violation**, because blockwatch can't tell which one you mean. Two
|
|
227
|
+
`### Example` sections under different `##` headings are fine.
|
|
228
|
+
- **Escape a heading like any key.** `## Input/Output` is `#/Input~1Output`, and `## Step 1: build` is
|
|
229
|
+
`#/Step 1%3A build`.
|
|
230
|
+
- **An `.mdx` file gets the same paths.** The text of a JSX element in a heading counts, and so does the code in
|
|
231
|
+
braces: `## Red <Badge>new</Badge> {version}` is `#/Red new version`. A heading inside a JSX element doesn't count.
|
|
232
|
+
A file that isn't valid MDX stops the run.
|
|
233
|
+
|
|
234
|
+
<!-- </block> -->
|
|
235
|
+
|
|
192
236
|
---
|
|
193
237
|
|
|
194
238
|
[← Return to README](../README.md)
|
|
@@ -23,7 +23,8 @@ between two references is fine.
|
|
|
23
23
|
|
|
24
24
|
## Which validator do I want?
|
|
25
25
|
|
|
26
|
-
<!-- <block name="validators-index"
|
|
26
|
+
<!-- <block name="validators-index"
|
|
27
|
+
affects="src/skill.md#/blockwatch/Annotating a new project/Where blocks add value (catalog)"
|
|
27
28
|
same-as="src/validators/mod.rs:validator-registry, README.md:available-validators"
|
|
28
29
|
same-as-pattern='\[`(?P<value>[a-z-]+)`\]\('> -->
|
|
29
30
|
|
|
@@ -8,13 +8,13 @@ It runs on every scan, with or without a diff.
|
|
|
8
8
|
|
|
9
9
|
## Syntax
|
|
10
10
|
|
|
11
|
-
| Attribute | Value
|
|
12
|
-
|
|
13
|
-
| `same-as` | One or more [targets](#targets), comma-separated
|
|
14
|
-
| `same-as-paths` | A [glob](#paths-as-targets) of paths to compare
|
|
15
|
-
| `same-as-pattern` | A regex that picks the values to compare
|
|
16
|
-
| `same-as-mode` | `set`, `sequence`, `single` or `subset`
|
|
17
|
-
| `same-as-format` | `numeric`, `identifier` or `flat
|
|
11
|
+
| Attribute | Value | Default |
|
|
12
|
+
|-------------------|--------------------------------------------------------------------------------------|-------------------|
|
|
13
|
+
| `same-as` | One or more [targets](#targets), comma-separated | — |
|
|
14
|
+
| `same-as-paths` | A [glob](#paths-as-targets) of paths to compare | — |
|
|
15
|
+
| `same-as-pattern` | A regex that picks the values to compare | the whole content |
|
|
16
|
+
| `same-as-mode` | `set`, `sequence`, `single` or `subset` | `set` |
|
|
17
|
+
| `same-as-format` | `numeric`, `identifier` or `flat`, or [one for each group](#a-format-for-each-group) | text |
|
|
18
18
|
|
|
19
19
|
## Targets
|
|
20
20
|
|
|
@@ -55,10 +55,10 @@ Usually, though, the two places don't hold the same text. Then each block says *
|
|
|
55
55
|
|
|
56
56
|
## Pick values with `same-as-pattern`
|
|
57
57
|
|
|
58
|
-
Each block has its own regex. Every match is a value: the `(?P<value>…)` group if
|
|
59
|
-
match. A
|
|
60
|
-
|
|
61
|
-
written in different formats:
|
|
58
|
+
Each block has its own regex. Every match is a value: the `(?P<value>…)` group if the pattern has one, otherwise the
|
|
59
|
+
whole match. A pattern with [other named groups](#compare-several-groups) compares those too. A line can hold several
|
|
60
|
+
values. Lines without a match are skipped, and so are empty matches. So is a match of a branch without the `value`
|
|
61
|
+
group: `^(?:none|(?P<value>\w+))$` skips the line `none`. This lets you compare blocks written in different formats:
|
|
62
62
|
|
|
63
63
|
```rust
|
|
64
64
|
// <block same-as="README.md:supported-env-vars" same-as-pattern="BLOCKWATCH_AI_[A-Z_]+">
|
|
@@ -76,6 +76,41 @@ const API_URL: &str = "BLOCKWATCH_AI_API_URL";
|
|
|
76
76
|
[//]: # (</block>)
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
### Compare several groups
|
|
80
|
+
|
|
81
|
+
A pattern can have several named groups, such as a code and its message. Then each match is one record, and the
|
|
82
|
+
records are compared whole. So a message that moves to another code fails, even though the messages alone still agree:
|
|
83
|
+
|
|
84
|
+
```rust
|
|
85
|
+
// <block same-as="docs/errors.md:errors" same-as-pattern='(?P<code>\d+) => "(?P<message>[^"]+)"'>
|
|
86
|
+
404 => "not found",
|
|
87
|
+
409 => "already exists",
|
|
88
|
+
// </block>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```markdown
|
|
92
|
+
<!-- <block name="errors" same-as-pattern="^- `(?P<code>\d+)`: (?P<message>.+)$"> -->
|
|
93
|
+
- `404`: already exists
|
|
94
|
+
- `409`: not found
|
|
95
|
+
<!-- </block> -->
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The run reports:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
[{code: "404", message: "not found"}, {code: "409", message: "already exists"}] != [{code: "404", message: "already exists"}, {code: "409", message: "not found"}]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **Groups match by name**, not by their place in the pattern. So one side can write the message before the code.
|
|
105
|
+
- **Both patterns need the same groups.** Otherwise the run reports
|
|
106
|
+
`same-as-pattern groups differ: code, message != message`.
|
|
107
|
+
- **A pattern without named groups has one group, `value`.** So does a block without a pattern. Either can be compared
|
|
108
|
+
with a pattern whose only group is `value`.
|
|
109
|
+
- **A match is skipped when one of its groups is not in the match, or is empty.**
|
|
110
|
+
- **A record must fit on one line,** because the pattern reads one line at a time.
|
|
111
|
+
- **`same-as-format` applies to every group,** unless you give [each group its own](#a-format-for-each-group).
|
|
112
|
+
- **To group part of a pattern without comparing it, use `(?:…)`.** It captures nothing.
|
|
113
|
+
|
|
79
114
|
### Lines are not part of the comparison
|
|
80
115
|
|
|
81
116
|
With a pattern, only the values count, not how they are split into lines. These two blocks agree, even in `sequence`
|
|
@@ -290,17 +325,45 @@ plain `s`, so `policies.yaml` gives `policie`, which doesn't equal `Policy`.
|
|
|
290
325
|
- **Digits and accents count.** `Version2` equals `version-2`, but not `version`. `CAFÉ` equals `café`, but not `cafe`.
|
|
291
326
|
- **Messages show each value as it is compared,** such as `crontab`.
|
|
292
327
|
|
|
328
|
+
## A format for each group
|
|
329
|
+
|
|
330
|
+
With [several groups](#compare-several-groups), each group can have its own format. Write `group:format` entries,
|
|
331
|
+
separated by commas. Here the names differ in style and the numbers differ in spelling:
|
|
332
|
+
|
|
333
|
+
```rust
|
|
334
|
+
// <block same-as="docs/config.md:defaults" same-as-format="name:identifier,value:numeric" same-as-pattern="const (?P<name>\w+): \w+ = (?P<value>[\d.]+);">
|
|
335
|
+
const MAX_RETRIES: u32 = 3;
|
|
336
|
+
const TIMEOUT_SECS: f64 = 2.0;
|
|
337
|
+
// </block>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
```markdown
|
|
341
|
+
<!-- <block name="defaults" same-as-pattern="^- `(?P<name>[a-z-]+)`: (?P<value>[\d.]+)$"> -->
|
|
342
|
+
- `max-retries`: 3
|
|
343
|
+
- `timeout-secs`: 2
|
|
344
|
+
<!-- </block> -->
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
- **A group without an entry is compared as written.** With `same-as-format="value:numeric"`, `MAX_RETRIES` and
|
|
348
|
+
`max-retries` differ.
|
|
349
|
+
- **A format without a group applies to every group.** With `same-as-format="numeric"`, the run reports that
|
|
350
|
+
`MAX_RETRIES` is not a number.
|
|
351
|
+
- **The two forms don't mix.** `identifier,value:numeric` is an error.
|
|
352
|
+
- **Each group must be a group of this block's pattern.** Otherwise the run stops, so a typo can't go unnoticed. A
|
|
353
|
+
block without a pattern, or a pattern without named groups, has the one group `value`. So `value:numeric` works
|
|
354
|
+
there too.
|
|
355
|
+
|
|
293
356
|
## Notes
|
|
294
357
|
|
|
295
358
|
- **Which block's attributes count.** The referencing block's `same-as-mode` and `same-as-format` decide how to compare.
|
|
296
359
|
Each block's `same-as-pattern` reads only that block. A whole file, a symbol or a list of paths has no block, so the
|
|
297
360
|
referencing block's pattern reads it too.
|
|
298
361
|
- **Violations:** a missing block, a missing or repeated key, a value that is not a number under `numeric`, a `single`
|
|
299
|
-
side without exactly one value, a pattern that matches nothing on either side,
|
|
300
|
-
matches no path. Two empty sides do not count as equal.
|
|
301
|
-
- **Errors that stop the run:** an unknown `same-as-mode` or `same-as-format`,
|
|
302
|
-
`same-as-paths` without `same-as-pattern`, a missing target
|
|
303
|
-
symbols, or with several YAML documents.
|
|
362
|
+
side without exactly one value, a pattern that matches nothing on either side, two patterns with different groups,
|
|
363
|
+
and a `same-as-paths` glob that matches no path. Two empty sides do not count as equal.
|
|
364
|
+
- **Errors that stop the run:** an unknown `same-as-mode` or `same-as-format`, a `same-as-format` entry for a group
|
|
365
|
+
that the pattern doesn't have, an invalid regex or glob, `same-as-paths` without `same-as-pattern`, a missing target
|
|
366
|
+
file, and a symbol in a file with a syntax error, without symbols, or with several YAML documents.
|
|
304
367
|
- **Run it on the whole tree now and then.** `same-as` needs no diff, so a plain `blockwatch` run catches drift that
|
|
305
368
|
`--only-changed` misses. See [CI integration](../ci.md).
|
|
306
369
|
- **A rename alone goes unnoticed in a diff.** Renaming a target file without changing it (a plain `git mv`) gives
|
|
@@ -6,7 +6,7 @@ setup(
|
|
|
6
6
|
name='blockwatch-pre-commit-placeholder',
|
|
7
7
|
version='0.0.0',
|
|
8
8
|
# <block name="blockwatch-cli-version" same-as-pattern="blockwatch-cli==(?P<value>\d+\.\d+\.\d+)">
|
|
9
|
-
install_requires=['blockwatch-cli==0.
|
|
9
|
+
install_requires=['blockwatch-cli==0.14.0'],
|
|
10
10
|
# </block>
|
|
11
11
|
# Without it, setuptools takes the directories under src/ for Python packages.
|
|
12
12
|
packages=[],
|
|
@@ -52,8 +52,9 @@ pub(crate) struct Content {
|
|
|
52
52
|
/// The text of a block's [`Content`].
|
|
53
53
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
54
54
|
enum ContentText {
|
|
55
|
-
/// The source text in this byte range: the lines between the block's tags, or the
|
|
56
|
-
///
|
|
55
|
+
/// The source text in this byte range: the lines between the block's tags, or the part of the
|
|
56
|
+
/// file that a virtual block wraps when it is written as is, such as a JSON object or a
|
|
57
|
+
/// Markdown section.
|
|
57
58
|
Source(Range<usize>),
|
|
58
59
|
/// The decoded value of the scalar that a virtual block wraps. Its quotes and escapes are
|
|
59
60
|
/// gone, so it is not a part of the source text.
|
|
@@ -93,7 +93,7 @@ mod tests {
|
|
|
93
93
|
"containers": [{"key": "value"}, ["item"]]
|
|
94
94
|
}"#;
|
|
95
95
|
|
|
96
|
-
// <block affects="docs/symbols.md:json-paths, src/skill.md
|
|
96
|
+
// <block affects="docs/symbols.md:json-paths, src/skill.md#/blockwatch/Symbols/JSON">
|
|
97
97
|
assert_eq!(
|
|
98
98
|
derived_symbols(source)?,
|
|
99
99
|
expected_symbols([
|