From e258d511800d2826a22eb524c0753dfbf12f4e8a Mon Sep 17 00:00:00 2001 From: lee-to Date: Fri, 20 Mar 2026 14:37:56 +0300 Subject: [PATCH 1/2] feat: Constraints with commands --- docs/ARCH.md | 10 +- docs/SPECS.md | 19 +- docs/WORKFLOW.md | 10 +- schema/constraint-schema.json | 21 + schema/security-constraints-schema.json | 21 + skills/implement/SKILL.md | 4 +- skills/validate/SKILL.md | 4 +- src/check/code_trace.rs | 4 + src/check/constraints.rs | 259 ++++++- src/cmd/check.rs | 21 + src/cmd/constraints.rs | 168 ++++- src/main.rs | 36 + src/mcp/mod.rs | 36 +- src/mcp/tools.rs | 29 +- src/model/policy.rs | 29 + tests/constraints_tests.rs | 858 +++++++++++++++++++++++- tests/mcp_tests.rs | 7 + 17 files changed, 1505 insertions(+), 31 deletions(-) diff --git a/docs/ARCH.md b/docs/ARCH.md index 2ed4f23..2c2304d 100644 --- a/docs/ARCH.md +++ b/docs/ARCH.md @@ -313,7 +313,7 @@ This is not dogma: for UI/frontend, bot/automation tasks, glue code, ML/data/AI- ### 5.2 Code Traceability (`@hlv` markers) -Every error code, invariant, and constraint rule from contracts MUST have an `@hlv ` marker next to the test that verifies it: +Every error code, invariant, and constraint rule from contracts MUST have an `@hlv ` marker next to the test that verifies it. Constraint rules that have `check_command` are exempt — they are verified programmatically: ```rust // @ctx: stock validation for order.create contract @@ -333,7 +333,7 @@ fn test_no_sql_injection() { ... } `@ctx` comments are navigation hints for the LLM. They help understand context quickly without reading the entire file. They are optional, but recommended for complex logic. -`hlv check` automatically collects all IDs from `contracts/*.yaml` (`errors[].code`, `invariants[].id`) and `constraints/*.yaml` (`rules[].id`), then scans `src/` and `tests/` for markers. Missing markers produce warning `CTR-010`; in phase `implemented` and later they block `/validate`. +`hlv check` automatically collects all IDs from `contracts/*.yaml` (`errors[].code`, `invariants[].id`) and `constraints/*.yaml` (`rules[].id`), then scans `src/` and `tests/` for markers. Rules with `check_command` are skipped (verified by their command via CST-050). Missing markers produce warning `CTR-010`; in phase `implemented` and later they block `/validate`. ### 5.3 Agent Protocol @@ -478,9 +478,11 @@ Architecture for managing constraint files in `human/constraints/`. **CRUD.** `hlv constraints add` creates a new YAML file from a `ConstraintFile` template. `add-rule` / `remove-rule` mutate the `rules[]` array inside an existing file. All operations follow: read file -> deserialize -> mutate -> serialize -> write. -**`hlv check` checks.** `CST-010` - file from `project.yaml -> constraints` not found. `CST-020` - duplicate `rule.id` values inside the file. `CST-030` - invalid severity. `CST-010`/`020` are errors (block `/verify`), `CST-030` is a warning. +**`hlv check` checks.** `CST-010` - file from `project.yaml -> constraints` not found. `CST-020` - duplicate `rule.id` values inside the file. `CST-030` - invalid `severity` or `error_level` value. `CST-050` - runs `check_command` for each constraint rule that has one; severity is determined by the rule's `error_level` override, or mapped from rule severity (`critical`/`high` -> error, `medium`/`low` -> warning). `CST-060` - runs file-level `check_command` on the constraint file itself; failure is always an error. `CST-010`/`020` are errors (block `/verify`), `CST-030` is a warning. -**Contract linkage.** Contracts refer to constraint rules through `depends_on_constraints`. `hlv check` (`CTR-010`) verifies that every `rule.id` from constraints has an `@hlv` marker in code. +**`hlv constraints check`.** Runs `check_command` for constraint rules with additional filters: `hlv constraints check `, `--rule `, `--json`. The same checks also run as part of `hlv check`. + +**Contract linkage.** Contracts refer to constraint rules through `depends_on_constraints`. `hlv check` (`CTR-010`) verifies that every `rule.id` from constraints has an `@hlv` marker in code. Rules that have `check_command` are exempt from the `@hlv` marker requirement — they are verified programmatically by their command. --- diff --git a/docs/SPECS.md b/docs/SPECS.md index aa279ea..05c3f42 100644 --- a/docs/SPECS.md +++ b/docs/SPECS.md @@ -469,8 +469,9 @@ CRUD management for constraint files in `human/constraints/`. Each file is a rul | `hlv constraints show [--json]` | Show the content of a constraint file (all rules, owner, intent) | | `hlv constraints add [--owner ] [--intent ] [--applies-to ]` | Create a new constraint file | | `hlv constraints remove [--force]` | Remove a constraint file. Without `--force`, confirmation is required | -| `hlv constraints add-rule --severity --statement ` | Add a rule to an existing constraint file | +| `hlv constraints add-rule --severity --statement [--check-command ] [--check-cwd ] [--error-level ]` | Add a rule to an existing constraint file. Optional: `--check-command` sets a shell command to verify the rule, `--check-cwd` sets the working directory, `--error-level` overrides diagnostic severity (`error`, `warning`, `info`) | | `hlv constraints remove-rule ` | Remove a rule from a constraint file | +| `hlv constraints check [] [--rule ] [--json]` | Run `check_command` for constraint rules. Optionally filter by constraint name or rule ID | `` is the file name without extension (for example `security` -> `human/constraints/security.yaml`). Severity values are `critical`, `high`, `medium`, `low`. @@ -531,6 +532,9 @@ rules: statement: "Secrets must not appear in logs" enforcement: - log_policy_check + check_command: "grep -rn 'secret\\|password' src/ && exit 1 || exit 0" + check_cwd: "llm" + error_level: error exceptions: process: "Requires security team approval" max_duration_days: 30 @@ -547,6 +551,9 @@ exceptions: | `rules[].severity` | enum | Severity: `critical`, `high`, `medium`, `low` | | `rules[].statement` | string | Rule wording | | `rules[].enforcement[]` | array | Verification methods (`sast`, `integration_test`, `runtime_scan`, etc.) | +| `rules[].check_command` | string (optional) | Shell command to verify the rule (used by `CST-050` and `hlv constraints check`) | +| `rules[].check_cwd` | string (optional) | Working directory for `check_command` (relative to project root; defaults to project root) | +| `rules[].error_level` | enum (optional) | Override diagnostic severity: `error`, `warning`, `info`. If unset, mapped from `severity` (`critical`/`high` -> error, `medium`/`low` -> warning) | | `exceptions` | object | Exception process (`process`, `max_duration_days`) | Rust model: `model::policy::ConstraintFile`. Schema: `schema/constraint-schema.json`. @@ -561,7 +568,9 @@ Integrity checks for constraint files, executed by `hlv check`. |-----|---------|--------------| | `CST-010` | error | Constraint file referenced in `project.yaml -> constraints` is not found on disk | | `CST-020` | error | Duplicate `rule.id` values within the same constraint file | -| `CST-030` | error | Invalid `severity` value (allowed: `critical`, `high`, `medium`, `low`) | +| `CST-030` | error | Invalid `severity` value (allowed: `critical`, `high`, `medium`, `low`) or invalid `error_level` (allowed: `error`, `warning`, `info`) | +| `CST-050` | varies | Runs `check_command` for a constraint rule. Severity is determined by `error_level` override, or mapped from rule severity (`critical`/`high` -> error, `medium`/`low` -> warning) | +| `CST-060` | error | Runs file-level `check_command` on the constraint file. Failure is always an error | These checks run automatically as part of `hlv check` and block `/verify` when reported as errors. @@ -597,7 +606,7 @@ Important notes: | `CTR-002` | error | Missing contract ID in Markdown header | | `CTR-003` | error | Missing contract version in Markdown header | | `CTR-004` | error | Markdown contract version differs from `project.yaml` | -| `CTR-010` | error / warning | Missing required contract section (error) or missing `@hlv` marker in code trace (warning) | +| `CTR-010` | error / warning | Missing required contract section (error) or missing `@hlv` marker in code trace (warning). Constraint rules with `check_command` are exempt from the marker requirement | | `CTR-020` | warning | Contract source link points to missing file | | `CTR-030` | error | Invalid Input YAML block in contract Markdown | | `CTR-031` | error | Missing Input YAML block in contract Markdown | @@ -670,7 +679,9 @@ Important notes: |-----|---------|--------------| | `CST-010` | error | Constraint file is missing or unparsable | | `CST-020` | error | Duplicate `rules[].id` in one constraint file | -| `CST-030` | error | Invalid `rules[].severity` | +| `CST-030` | error | Invalid `rules[].severity` or `rules[].error_level` | +| `CST-050` | varies | Rule-level `check_command` failed (severity from `error_level` or mapped from rule severity) | +| `CST-060` | error | File-level `check_command` failed | #### LLM Map (`MAP-*`) diff --git a/docs/WORKFLOW.md b/docs/WORKFLOW.md index 36c2f06..416e4d9 100644 --- a/docs/WORKFLOW.md +++ b/docs/WORKFLOW.md @@ -335,7 +335,7 @@ Agents work in parallel inside a group. Between groups - git commit. **`llm/map.yaml` is the main navigator.** When creating a new file, the agent MUST add an entry to `llm/map.yaml` with a description sufficient to choose the file without opening it. The LLM finds code by descriptions in `map.yaml`, not by file names. `hlv check` verifies that all entries exist on disk. -**`@hlv` markers.** Every test must carry an `@hlv ` marker pointing to an error code, invariant, or constraint rule from contracts. This provides 100% contract->code traceability. `hlv check` verifies that all IDs are covered. Example: +**`@hlv` markers.** Every test must carry an `@hlv ` marker pointing to an error code, invariant, or constraint rule from contracts. This provides 100% contract->code traceability. `hlv check` verifies that all IDs are covered. Constraint rules that have `check_command` are exempt — they are verified by their command, not by markers. Example: ```rust // @ctx: validates stock availability check from order.create contract @@ -543,7 +543,7 @@ hlv milestone abort # abort milestone /generate # artifacts -> contracts + validation + stages # Verification -hlv check # structural validation + run gate commands +hlv check # structural validation + run gate commands + constraint checks (CST-050) hlv check --watch # same + watch /verify # full verification (structure + semantics) @@ -581,6 +581,12 @@ hlv stage meta set|delete [] hlv milestone label add|remove