diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f0ff7bc..8e3cfc1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,10 @@ permissions: jobs: test: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python: ["3.10", "3.12"] steps: - name: Check out repository uses: actions/checkout@v4 @@ -19,9 +23,11 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: ${{ matrix.python }} - name: Run local verification suite run: | make test test-verify-ui python3 scripts/build_public_contracts.py + - name: Verify installed wheel outside the checkout + run: python3 scripts/test_package_consumer.py diff --git a/ADOPTION.md b/ADOPTION.md index ed21dba..12cf091 100644 --- a/ADOPTION.md +++ b/ADOPTION.md @@ -2,10 +2,11 @@ ## Version-aware adoption -Existing supported legacy guides keep their current evaluation when checked by -the 1.0.0 dispatcher. No guide, manifest, DNS, or repository-anchor -rotation is required for that compatibility. The latest released profile is -[1.0.0](profiles/1.0.0/spec.md); legacy profiles remain supported. +Existing supported legacy guides keep their current evaluation under the 2.0.0 +candidate dispatcher. No guide, manifest, DNS, or repository-anchor rotation +is required for that compatibility. The current candidate is +[2.0.0](profiles/2.0.0/spec.md) and is unpublished; [1.0.0](profiles/1.0.0/spec.md) +remains the last published profile, and legacy profiles remain supported. Deliberately adopting 1.0.0 requires matching guide/manifest profile declarations and another qualifying anchor when the repository was the only source of @@ -15,9 +16,17 @@ Consumers that require 1.0.0 can use the `required_profile_version` API field or `--require-profile-version` local CLI assertion. These reject an incompatible guide rather than reinterpret its bytes. Local evaluation still caps at Level 3. +Deliberately adopting the 2.0.0 candidate requires matching guide and manifest +profile declarations. Its `corrected-content-1` policy is opt-in and its +`1.0.0-strict` anchor policy still excludes repository-file evidence from Level +4 qualification. It does not migrate existing reports. The experimental POSIX +CLI selector, `--contract posix-json-v1`, is independent of the guide-declared +profile selector; see [the CLI contract](docs/cli-contract.md). + The guidance below describes the published legacy profile. See the -[compatibility contract](docs/anchor-policy-compatibility.md) for version selection -and the [validation evidence](docs/anchor-dispatch-validation.md) for tested limits. +[compatibility contract](docs/anchor-policy-compatibility.md), +[corrected-content policy](docs/corrected-content-policy-2026-09-07.md), and +[candidate release notes](RELEASE_NOTES-2.0.0.md) for selection and status. This is the practical on-ramp to GuideCheck. It explains what an `assistant-guide.txt` artifact is, what the conformance ladder means in diff --git a/CHANGELOG.md b/CHANGELOG.md index 8644c76..b9edfe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,22 @@ All notable changes to GuideCheck's Human-Verifiable Assistant Guide profile and its companion documents are recorded here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) conventions. Profile versions follow Semantic Versioning as defined in `spec.md` section 11. -## [Unreleased] +## [2.0.0] - 2026-09-07 (unreleased candidate) + +- Include the corrected evaluator in the installable wheel and exercise legacy, + strict, corrected, and scanner dispatch from an isolated installed consumer in CI. +- Add the experimental `--contract posix-json-v1` verification adapter with one + terminal JSON record, separate operational and gate outcomes, and stable exit + categories. Existing CLI output and exit behavior remain the default. +- Freeze complete released 1.0.0 local and hosted reports in compatibility + replays alongside the existing legacy baseline. +- Add the root assistant-guide manifest and enforce byte equality with the + served copy, preserving published self-guide and manifest bytes. +- Add a local, unreleased 2.0.0 profile candidate selected only by guide bytes. + It corrects bounded negation and independent occurrence matching, blocks + unresolved execution targets, recognizes syntax-proven repository dispatch, + and inherits the released 1.0.0 strict anchor policy without changing legacy + or 1.0.0 reports. ## [1.0.0] - 2026-09-05 diff --git a/CLAUDE.md b/CLAUDE.md index 260fcd2..5d403f1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -53,6 +53,7 @@ Canonical site: https://guidecheck.org/ · Verifier: https://guidecheck.org/veri 3ceb30a evaluator and 0.7.1 report contract; frozen artifact digests and full report replays guard compatibility. - `guidecheck_strict.py` implements the opt-in 1.0.0 provenance policy. + - `guidecheck_corrected.py` implements the opt-in 2.0.0 corrected-content policy. - `guidecheck_verify.py` — local-file reference verifier CLI (Levels 1-3, plus internal-consistency checks on Level 4 sidecar manifests/anchors). - `guidecheck_scan.py` / `guidecheck_cli.py` — instruction-surface scanner @@ -84,8 +85,9 @@ Canonical site: https://guidecheck.org/ · Verifier: https://guidecheck.org/veri consistent with them, not the other way around. - Software, engine, released-profile, and self-guide versions are separate in `scripts/guidecheck_constants.py`. The legacy engine has frozen constants. - `scripts/check_version_sync.py` checks release surfaces against 1.0.0 and legacy/self-guide surfaces against 0.7.1; - package upgrades must not rewrite the published self-guide or its anchors. + `scripts/check_version_sync.py` checks the 2.0.0 candidate surfaces while + legacy/self-guide surfaces remain 0.7.1; candidate work must not rewrite the + published self-guide or its anchors. - `finding-ids.md` is the normative registry for finding ids; new finding ids used by fixtures or emitted by verifiers/scanner must be registered there (see `CONTRIBUTING.md`). @@ -129,7 +131,8 @@ builds and Sigstore-signs release + conformance-kit artifacts. ## Current state -- Released, profile version 1.0.0 (see `CHANGELOG.md`). +- The current candidate is 2.0.0 and is unpublished. Profile 1.0.0 remains the + last published profile (see `CHANGELOG.md`). - Most recent work (2026-07-07): added `guidecheck scan`, a standalone instruction-surface scanner for existing files (AGENTS.md/CLAUDE.md/ README/SKILL/llms.txt/assistant-guide.txt) that flags hidden-instruction @@ -162,3 +165,12 @@ the deterministic DOM contract separately. CI runs both. Local bounded-execution findings are implemented in the shared verifier. Pins remain unverified, including through hosted callers. See roadmap.md for pending hosted fetching and independence decisions. Legacy profile behavior remains pinned to the pre-dispatch baseline. + +## Corrected-content candidate (2026-09-07) + +The opt-in 2.0.0 candidate selects `corrected-content-1` while retaining the +`1.0.0-strict` anchor policy. See `docs/corrected-content-policy-2026-09-07.md` +and `RELEASE_NOTES-2.0.0.md`. It does not publish, migrate, or reinterpret +legacy, 1.0.0, or self-guide bytes. The experimental POSIX CLI selector +`--contract posix-json-v1` is independent of the guide-declared profile +selector; see `docs/cli-contract.md`. diff --git a/INTENT.md b/INTENT.md index fe6e098..b846630 100644 --- a/INTENT.md +++ b/INTENT.md @@ -77,7 +77,23 @@ GuideCheck is a PAICE Foundation standard. It sits alongside the other open-spec ## Versioning and authority -The current profile is declared in `profiles/1.0.0/spec.md` and tracked in `CHANGELOG.md`. The current version is 1.0.0, released. Root normative documents preserve the legacy contract; the self-guide remains pinned to 0.7.1. The version is asserted by `scripts/check_version_sync.py` against `scripts/guidecheck_constants.py` against independently pinned release, engine, and self-guide identities, so the status here and the released tag cannot silently disagree. `spec.md` and `verifier-conformance.md` are normative. `design-rationale.md` and `threat-register.md` are explanatory and must stay consistent with the normative documents. `archive/` is historical and is not edited. +The current candidate version is 2.0.0, declared in `profiles/2.0.0/` and not +published. Profile 1.0.0 remains the last published profile and is tracked in +`CHANGELOG.md`. Root normative documents preserve the legacy contract; the +self-guide remains pinned to 0.7.1. `scripts/check_version_sync.py` asserts +candidate, engine, and self-guide identities without treating the candidate as +a published release. `spec.md` and `verifier-conformance.md` are normative. +`design-rationale.md` and `threat-register.md` are explanatory and must stay +consistent with the normative documents. `archive/` is historical and is not +edited. + +## Corrected content checks + +Decided by Sam on 2026-09-07: preserve frozen legacy reports and add an explicitly selected corrected evaluation path. The September 7 detector review reproduced negation false positives, affirmative-instruction false negatives, and unpinned script-dispatch gaps. These are maintenance of existing content-check obligations, not authority to silently alter a published evaluation contract. + +Existing supported profile behavior, findings, levels, report identity, and exit semantics remain frozen. The corrected path has explicit 2.0.0 selection and `corrected-content-1` policy identity, as defined in `docs/corrected-content-policy-2026-09-07.md`. This does not revise the published strict 1.0.0 policy, which reuses legacy content checks. Publication and hosted acceptance are not completed by this candidate. + +Sam also decided on 2026-09-07 that an unresolved execution target blocks Level 3 acceptance on the corrected path. The guide must establish the effective target and satisfy the applicable pinning contract. A declared hash alone cannot resolve an unidentified target. This requirement does not change any released legacy or 1.0.0 evaluation. ## Maintenance and demand gate @@ -90,6 +106,8 @@ standard scope or authorize a cross-standard certification product. The Septembe ## Changelog +- 2026-09-07: Sam selected blocking unresolved execution targets for Level 3 on the opt-in corrected path; released evaluations remain frozen. +- 2026-09-07: Sam selected preservation of frozen legacy reports with opt-in corrected content checks. Recorded the decision and remaining selector/version design scope; evaluator and published profiles remain unchanged. - 2026-09-05: Sam approved the version-aware anchor proposal with legacy compatibility required. The local 1.0.0 candidate excludes repository-file evidence from independent qualification, while the dispatcher preserves supported legacy evaluations and published self-guide bytes. Release and deployment remain separate. See `docs/anchor-policy-compatibility.md` and `docs/anchor-dispatch-validation.md`. - 2026-07-31: Opened the canonical approval receipt as a live open question, prompted by an external question about binding approval to the exact executing action. Detail in `roadmap.md`; the identity fork (field in the record versus signer over it) is the first thing to resolve, gated behind Level 5 fixture-suite design. diff --git a/Makefile b/Makefile index 00998c6..a242d73 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,11 @@ -.PHONY: test-verify-ui test-legacy-anchor-compatibility test-bounded-execution eval verify-fixtures validate-contracts test-contract-schema-validation test-parser-edge-cases check-guide-artifacts check-version-sync test-fetch-safety test-hosted-anchors test-hosted-api test-fetch-replay test-cli-contract test-scanner test release-archive conformance-kit +.PHONY: test-verify-ui test-legacy-anchor-compatibility test-bounded-execution test-corrected-content eval verify-fixtures validate-contracts test-contract-schema-validation test-parser-edge-cases check-guide-artifacts check-version-sync test-fetch-safety test-hosted-anchors test-hosted-api test-fetch-replay test-cli-contract test-scanner test release-archive conformance-kit VERSION := $(shell python3 -c "import sys; sys.path.insert(0, 'scripts'); from guidecheck_constants import GUIDECHECK_VERSION; print(GUIDECHECK_VERSION)") +.PHONY: test-package-consumer test-posix-cli-contract +test-package-consumer: + python3 scripts/test_package_consumer.py + eval: python3 scripts/eval_guidecheck.py @@ -38,22 +42,29 @@ test-fetch-replay: test-cli-contract: python3 scripts/test_cli_contract.py +test-posix-cli-contract: + python3 scripts/test_posix_cli_contract.py + test-scanner: python3 scripts/test_scanner.py test-bounded-execution: python3 scripts/test_bounded_execution.py +test-corrected-content: + python3 scripts/test_corrected_content.py + test-legacy-anchor-compatibility: python3 scripts/test_legacy_anchor_compatibility.py python3 scripts/test_dispatch_compatibility.py + python3 scripts/test_strict_compatibility.py python3 scripts/test_profile_dispatch.py # Keep the established Python-only test entry point usable without Node. test-verify-ui: node scripts/test_verify_ui.mjs -test: test-legacy-anchor-compatibility test-bounded-execution eval verify-fixtures validate-contracts test-contract-schema-validation test-parser-edge-cases check-guide-artifacts check-version-sync test-fetch-safety test-hosted-anchors test-hosted-api test-fetch-replay test-cli-contract test-scanner +test: test-legacy-anchor-compatibility test-bounded-execution test-corrected-content eval verify-fixtures validate-contracts test-contract-schema-validation test-parser-edge-cases check-guide-artifacts check-version-sync test-fetch-safety test-hosted-anchors test-hosted-api test-fetch-replay test-cli-contract test-posix-cli-contract test-scanner # Full source archive for a GitHub release, matching prior build/ layout. release-archive: diff --git a/PROJECT_CONTEXT.md b/PROJECT_CONTEXT.md index fdb9f56..2dd9dcc 100644 --- a/PROJECT_CONTEXT.md +++ b/PROJECT_CONTEXT.md @@ -64,7 +64,8 @@ notes), rather than a general PAICE-wide default. ## Current status -Released, profile version 1.0.0 (see `CHANGELOG.md`). Most recent shipped work: +The current candidate is 2.0.0 and is unpublished; 1.0.0 remains the last +published profile (see `CHANGELOG.md`). Most recent shipped work: `guidecheck scan`, an instruction-surface scanner for pre-existing AGENTS.md/CLAUDE.md/README/SKILL/llms.txt-style files (2026-07-07). Undecided/open items live in @@ -84,3 +85,13 @@ and delivery limits are in `docs/anchor-dispatch-validation.md`. Local bounded-execution findings are implemented in the shared verifier. Pins remain unverified, including through hosted callers. See roadmap.md for pending hosted fetching and independence decisions. Legacy profile behavior remains pinned to the pre-dispatch baseline. + +## Corrected-content candidate (2026-09-07) + +The 2.0.0 candidate adds an explicitly selected `corrected-content-1` policy +while retaining the `1.0.0-strict` anchor policy. Legacy and 1.0.0 profiles, +their reports, and the 0.7.1 self-guide remain frozen. Candidate status and +scope are recorded in `RELEASE_NOTES-2.0.0.md` and +`docs/corrected-content-policy-2026-09-07.md`. The experimental POSIX CLI +selector `--contract posix-json-v1` is independent of the guide-declared +profile selector; see `docs/cli-contract.md`. diff --git a/README.md b/README.md index a7c6db2..e53e288 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # GuideCheck -The 1.0.0 dispatcher preserves legacy -verification and selects stricter repository-anchor rules only for guides that -declare 1.0.0. See the [1.0.0 profile](profiles/1.0.0/spec.md), -[compatibility contract](docs/anchor-policy-compatibility.md), and -[validation evidence](docs/anchor-dispatch-validation.md). Published guide and -anchor bytes remain unchanged at 0.7.1; the latest released profile is 1.0.0. +The 2.0.0 candidate adds an opt-in corrected content policy while preserving +legacy and 1.0.0 evaluations. It is unpublished: 1.0.0 remains the last +published profile, and the self-guide and frozen legacy reports remain 0.7.1. +See the [2.0.0 candidate profile](profiles/2.0.0/spec.md), +[corrected-content policy](docs/corrected-content-policy-2026-09-07.md), and +[candidate release notes](RELEASE_NOTES-2.0.0.md). The current candidate is 2.0.0. GuideCheck is a trust boundary protocol for agent instruction surfaces. It ensures the instructions humans approve are the same instructions agents @@ -98,7 +98,8 @@ agents may execute another. ## Documents - `ADOPTION.md` - the practical on-ramp: conformance ladder, level-by-level path, guide-author checklist -- `profiles/1.0.0/spec.md` and `profiles/1.0.0/verifier-conformance.md` - the current normative guide and verifier profiles +- `profiles/2.0.0/spec.md` and `profiles/2.0.0/verifier-conformance.md` - the unpublished 2.0.0 candidate guide and verifier profiles +- `profiles/1.0.0/spec.md` and `profiles/1.0.0/verifier-conformance.md` - the last published guide and verifier profiles - `spec.md` and `verifier-conformance.md` - preserved normative legacy profiles - `design-rationale.md` - why the design choices were made - `operator-guide.md` - non-normative defense-in-depth practices for operators @@ -257,7 +258,9 @@ expectation contract by `scripts/check_reference_verifier.py`. ## Status -Released, profile version 1.0.0. Legacy profiles remain supported. See `CHANGELOG.md`. +The current candidate is 2.0.0 and is unpublished. Profile 1.0.0 remains the +last published profile; legacy profiles remain supported. See +`RELEASE_NOTES-2.0.0.md` and `CHANGELOG.md`. This is an early-stage open standard. The most useful feedback right now is whether the hidden-instruction problem maps to real operational risk in your diff --git a/RELEASE_NOTES-2.0.0.md b/RELEASE_NOTES-2.0.0.md new file mode 100644 index 0000000..b540fc6 --- /dev/null +++ b/RELEASE_NOTES-2.0.0.md @@ -0,0 +1,22 @@ +# GuideCheck 2.0.0 candidate release notes + +Candidate version: 2.0.0 + +Status: Unpublished candidate. This file does not announce a tag, package, +GitHub Release, deployment, or hosted-service update. + +GuideCheck 2.0.0 adds the opt-in `corrected-content-1` policy for guides that +explicitly declare profile 2.0.0. It retains the `1.0.0-strict` anchor policy: +repository-file evidence remains corroborating and cannot qualify a guide for +Level 4. An unresolved execution target blocks Level 3 under this policy. + +The candidate preserves the isolated 0.7.1 legacy engine, the published 1.0.0 +profile, the 0.7.1 self-guide, and all frozen reports. Existing guides are not +migrated or reinterpreted automatically. + +The experimental POSIX JSON CLI contract, selected with +`--contract posix-json-v1`, is independent of the guide-declared profile +selector. See `docs/cli-contract.md`. + +The normative corrected-content policy is +`docs/corrected-content-policy-2026-09-07.md`. diff --git a/api/verify.py b/api/verify.py index ac77e2e..48a26c2 100644 --- a/api/verify.py +++ b/api/verify.py @@ -43,6 +43,7 @@ import guidecheck_verify as gv # noqa: E402 from guidecheck_profiles import ProfileError, select_profile # noqa: E402 from guidecheck_strict import decorate_report # noqa: E402 +from guidecheck_corrected import decorate_report as decorate_corrected_report # noqa: E402 from guidecheck_constants import GUIDECHECK_VERSION, HOSTED_VERIFIER_NAME, LEGACY_ENGINE_VERSION # noqa: E402 from guidecheck_fetch import FetchError, safe_fetch, variation_request_profile # noqa: E402 from guidecheck_hosted_anchors import ( # noqa: E402 @@ -738,10 +739,13 @@ def build_evaluated( if note: result["location_note"] = note result["compact_report"] = _compact_report(result) - if selection is not None and selection.strict: + if selection is not None and selection.modern: for anchor in result.get("cross_channel_anchors", []): anchor.update((anchor_sources or {}).get(anchor["channel"] + " anchor", {})) - decorate_report(result, selection) + if selection.corrected: + decorate_corrected_report(result, selection) + else: + decorate_report(result, selection) return result diff --git a/assistant-guide-manifest.txt b/assistant-guide-manifest.txt new file mode 100644 index 0000000..b72efd4 --- /dev/null +++ b/assistant-guide-manifest.txt @@ -0,0 +1,11 @@ +guide-path: /.well-known/assistant-guide.txt +guide-version: 0.7.1 +guide-sha256: 4b30202c809a3db037290371da8fed6a9681255199e0e19cfe1a0a7fc1d5df9e +guide-bytes: 8065 +immutable-release-url: https://github.com/snapsynapse/guidecheck/releases/tag/v0.7.1 +profile: human-verifiable-assistant-guide +profile-version: 0.7.1 +canonical-url: https://guidecheck.org/.well-known/assistant-guide.txt +repository-url: https://github.com/snapsynapse/guidecheck +released-at: 2026-07-21T00:00:00Z +changelog-url: https://github.com/snapsynapse/guidecheck/blob/v0.7.1/CHANGELOG.md diff --git a/docs/cli-contract.md b/docs/cli-contract.md new file mode 100644 index 0000000..1e19e3c --- /dev/null +++ b/docs/cli-contract.md @@ -0,0 +1,39 @@ +# Experimental CLI contract +`guidecheck verify` preserves its existing output and exit behavior unless the caller explicitly passes `--contract posix-json-v1`. The selector is experimental. It does not select or reinterpret a GuideCheck profile. `guidecheck scan` does not implement this contract. +## Process boundary +The selected contract writes exactly one terminal JSON object to stdout. Help text may be written to stderr. The terminal object follows `schemas/cli-result-posix-json-v1.json` and separates operational completion from the requested verification gate. +If a selected invocation ends without that terminal object, the run is incomplete. Diagnostics do not substitute for a terminal record. +`operational.status: complete` means the local verifier evaluated the guide and produced the nested `report`. It does not mean the guide passed. The `report` value is the established GuideCheck verifier report without renamed or removed fields. `legacy_exit_code` records the exit status the ordinary verifier invocation would have returned for the same evaluated report and gate flags. +Contract help completes without requesting verification, so its terminal record has `gate.status: not_requested` and no report. +GuideCheck's schema shares the A11y pilot's contract identity, operational result, gate status, terminal marker, and exit-status conventions. Its schema is tool-specific. The A11y adapter models a multi-stage pipeline and accessibility gate modes; GuideCheck models one local verification operation, uses `gate.mode: verify`, and nests the established verifier report. Consumers must validate against the GuideCheck schema. +The local verifier evaluates Levels 1 through 3. It can check local Level 4 sidecar and anchor consistency, but it cannot establish fetched provenance or award Level 4. When `--level 4` is the only unmet gate, the contract reports `inconclusive` rather than treating the local capability limit as proof of nonconformance. Blocking findings and a requested warning failure take rejection precedence. +`--format text` and `--pretty` cannot be combined with the selected contract because the contract owns stdout. `--json` is accepted as a redundant JSON assertion. Without `--contract posix-json-v1`, all three retain their established behavior. +The selected parser rejects abbreviated options, unknown selectors, duplicate singular options, and repeated `--anchor` channels. `--anchor` may be repeated only for distinct channels. Text after a literal `--` remains a path argument and does not select the contract. +Contract options use separate values only: write `--contract posix-json-v1`, not `--contract=posix-json-v1`. +| Error id | Remediation | +|---|---| +| `invalid-invocation`, `unsupported-option-syntax`, `missing-contract-value`, `unsupported-contract`, `duplicate-option`, `conflicting-output-option`, `duplicate-anchor-channel` | Correct the contract arguments and run the command again. | +| `invalid-profile-data`, `invalid-input-text` | Correct the guide, sidecar, or profile assertion before repeating. | +| `guide-input-missing`, `manifest-input-missing`, `anchor-input-missing` | Provide the missing local input path. | +| `input-permission-denied` | Grant read access to the named input. | +| `input-io-failure` | Resolve the identified local I/O condition. | +| `operational-failure` | Inspect stderr and reconcile the local verifier state before repeating. | +## Exit status +| Status | Meaning | +|---|---| +| 0 | Verification completed and the requested gate accepted, or contract help completed. | +| 2 | Verification completed with a confirmed gate rejection. | +| 3 | Verification completed, but local evaluation cannot establish the requested Level 4 result. | +| 64 | The contract invocation is malformed or uses an unsupported option, selector, or output flag. | +| 65 | The requested profile or guide profile data is invalid or unsupported. | +| 66 | A required guide, manifest, or anchor input is missing. | +| 74 | The verifier has specific file I/O failure evidence. | +| 77 | The verifier has specific permission-denied evidence. | +| 1 | Verification failed without evidence for a narrower category. | +`retryable` and `safe_to_repeat` are conservative. Operational failures set both to false. The contract does not infer a category from diagnostic prose. +## Invocation +Replace: GUIDE_PATH -> reviewed local assistant-guide.txt path +Customize +```bash +guidecheck verify GUIDE_PATH --contract posix-json-v1 +``` diff --git a/docs/corrected-content-policy-2026-09-07.md b/docs/corrected-content-policy-2026-09-07.md new file mode 100644 index 0000000..bd4dbd6 --- /dev/null +++ b/docs/corrected-content-policy-2026-09-07.md @@ -0,0 +1,239 @@ +# Corrected content policy contract + +Status: implemented local candidate contract, 2026-09-07. The profile documents, +schemas, fixtures, selectors, and callers named below agree; profile 2.0.0 remains +unreleased and undeployed. + +## Decision + +Add the corrected checks as profile `2.0.0`. A guide selects them only by +declaring exactly one `profile: human-verifiable-assistant-guide` and exactly +one `profile-version: 2.0.0` in its metadata block. Build metadata MAY identify +an equivalent build, such as `2.0.0+build.1`, and MUST resolve to policy +`2.0.0` as existing selectors do. + +This is the smallest honest selector. The corrected checks tighten some cases +and relax false-positive cases, so the repository's SemVer rule requires a +major profile version. A CLI flag, hosted request field, manifest assertion, +or caller-supplied `ProfileSelection` MUST NOT reinterpret guide bytes as +`2.0.0`. `--require-profile-version 2.0.0` and the hosted equivalent remain +assertions that fail when the guide does not declare the required profile. + +Profile `2.0.0` has these policy identities: + +- content policy: `corrected-content-1` +- anchor policy: `1.0.0-strict` +- evaluated policy: `2.0.0` + +Supported legacy declarations through `0.7.1` continue to select the frozen +legacy engine. A `1.0.0` declaration continues to select the released strict +anchor policy with frozen content checks. Neither path gains corrected checks, +new findings, changed levels, changed report fields, or changed exit behavior. + +## Anchor composition + +Profile `2.0.0` inherits the complete `1.0.0-strict` anchor contract: + +- repository-file evidence is corroboration and never establishes independent + provenance or qualifies for Level 4 +- a fetched matching non-repository qualifying channel is required for Level 4 +- matching local evidence cannot establish independence and local-file mode is + capped at Level 3 +- manifest `profile` and `profile-version` must match the selected guide profile + exactly, so a `2.0.0` guide requires a `2.0.0` manifest +- mismatches, unsupported channels, qualification reasons, and Level 5 + readiness retain the released strict semantics + +Content and anchor policy are composed after one request-local selection from +the guide bytes. Content findings may limit the achieved level, but they do not +change which anchor channels qualify. Anchor evidence does not suppress or +reinterpret content findings. The implementation MUST NOT mutate global +policy state, monkey-patch the legacy evaluator, or modify +`scripts/guidecheck_legacy.py`. + +## Corrected content behavior + +The new content engine segments prose before matching. Sentence punctuation, +semicolons, blank lines, action markers, metadata and structured fields, list +items, and headings terminate negation scope. One ordinary LF or CRLF prose +wrap does not terminate a directly governing phrase. + +Each prohibited instruction occurrence is matched independently using token +boundaries and bounded, non-greedy spans. A later affirmative instruction is +reported even when an earlier occurrence in the same prose unit is prohibited. +A direct negation may suppress its governed phrase across one prose wrap. A +comma-coordinated prohibition is recognized only for a narrow verb-phrase list +with an explicit conjunction. An intervening subject, contrast, temporal or +conditional term, sentence, structured boundary, or unrelated reassurance +ends governance. Ambiguous grammar does not suppress a finding. + +The 29 cases in the September 7 reproducer define the initial direct detector +contract. In particular: + +| Case | Corrected result | +|---|---| +| `Do not` plus one wrapped encoded-execution phrase | no encoded-execution finding | +| coordinated `Do not broaden ..., disable ..., or persist ...` | no skip-approval finding | +| affirmative encoded-execution phrase across one wrap | `prohibited.encoded-execution` error | +| negated occurrence followed by an affirmative occurrence | `prohibited.encoded-execution` error | +| sentence, paragraph, field, list, heading, action, contrast, subject, or temporal boundary | affirmative occurrence remains an error | + +No new prohibited-instruction finding ID is required for these cases. Existing +IDs retain their meanings and severities on the corrected path. + +## Bounded execution behavior + +The corrected path distinguishes syntax-proven repository dispatch from cases +whose ownership cannot be decided from the command. It MUST emit the new +`action.exec-target-unresolved` finding for an unresolved code-executing +target. `ambiguous` is an explicit review result, not a clean result. + +Sam decided on 2026-09-07 that `action.exec-target-unresolved` is an error. It +blocks Level 3 because the verifier cannot establish which bytes the action +executes. A declared hash cannot clear the finding by itself: until the target +is identified, the verifier cannot establish what those declared hash bytes +would bind. + +| Command shape | Classification | Reason or counterexample | +|---|---|---| +| `npm run