Repository navigation
Conversation
Kosli policies repeat long paths: every attestation sits at
`compliance_status.attestations_statuses.<name>.attestation_data`. A
subject can now name a path inside itself once, under `has:`, and its
checks use the name. Each entry is a part. Its key is the part's alias,
and its value is a path, or an object with `from` and `identified_by`.
Nothing reads `identified_by` yet, but it is checked and shown.
A part's alias stands for its path. `coverage.attestation_data.hunks_total`
gives the same passed, cause and values as the path written out, whether
the part is there, missing, `null` or the wrong type. Only the names in the
row's `expression`, `inputs` and `failed_items` keep the alias. This holds
because ergo puts the part's steps into the check's path before it reads
anything, and shows the alias in place of them. A test runs about 60 checks,
in sentences and in the old syntax, with the alias and with the full path,
on every kind of bad input, and compares the rows.
An alias is read wherever a bare first key reads the subject: in checks, in
`for` assertions, in the conditions of the subject's `from` line and of a
subject that narrows it. It isn't read in a `whose` or in the argument of a
one-line `every` or `some`. A subject that narrows another keeps its parts
and can add its own. A chained subject reads its parent's parts as
`artifact.pr_attestation.approvers`, and its `from` can start from one.
The old syntax reads a part as `$coverage`.
Written wrong, with the part's alias in the `$well_formed` name:
- `has` that isn't an object, a part that isn't a string or an object, no
`from`, a field other than `from` and `identified_by`
- a path that doesn't parse, has `whose`, `count of` or `named by each of`,
or starts at `$params` or `$input`
- an alias that isn't a bare word, or is a word of the grammar, `params` or
`input`
- an alias given twice: two parts, one kept from a narrowed subject, a `for`
alias, a chained subject's parent name, an old `as` or `each_as`
- `named by` an alias that is a part, which isn't supported yet because it
would read the subject's field of that name
`as_sentences` leaves a check that names an alias as written, because a
sentence would read the part where the old check read the field.
The report's `subjects` section lists every part, kept ones included, as
`{"from": ..., "identified_by": ...}`. The spec has the rules (`parts.*`,
`name.part`, `sentence.path.part`), 23 cases in `spec/cases/parts`, both
JSON Schemas, and `REFERENCE.md` has a Parts section. Open questions are in
`spec/OPEN.md`.
Changes the report: only for a policy that uses `has:`, and the `parts`
entry of each subject in `subjects`, which was always `{}`. A policy
without `has:` gives the same report: checked on every spec case and every
line of the sentence corpus, as a check, a from line and a for line (3008
reports).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2 of 4 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Third step of #244. A subject can declare parts: named paths inside it, which its checks read by their alias.
With this input:
{ "trail": { "name": "pr-491-r1", "compliance_status": { "attestations_statuses": { "findings": {"attestation_data": {"truncated": false}}, "coverage-verification": { "attestation_id": "att-7", "attestation_data": {"hunks_total": 25, "hunks_acknowledged": 25} } } } } }a policy can say:
fromwith an optionalidentified_by, read inside the part. Nothing usesidentified_byyet. The fourth step tags inputs with it.passed,causeand values. Only the names inexpressionandinputskeep the alias. The alias is expanded into the path when the policy is read, so this holds by construction.fromline conditions, and thewhoseof a subject that narrows it. It doesn't apply where a bare word reads an item instead, in thewhoseand the argument of a one-lineevery/some.alias given twice..namedoesn't get around an alias.artifact.pr_attestation.x, and itsfromcan start there.$coverage.partsin thesubjectssection lists every part as{"from": …, "identified_by": … or null}, kept ones included.Calls made while building it
named by <part alias>is written wrong, as not supported yet. Otherwise it would silently read the subject's field with that name.$paramsor$input: parts are paths inside the subject.ergo.as_sentencesleaves an old check as it was when any string in it equals one of its subject's part aliases, since turning["cov", "x"]intocov.xwould change its meaning.spec/OPEN.md. A walk that enters a list in the middle of a part's path names failed items likex.sub[1].y. And a chained subject whosefromstarts at a parent's part shows the full path in$min_subjectsand$unique_ids. Rows are correct in both cases.Checks
spec/check_grammar.pyfinds 0 disagreements.forlines, derived values,whose, and the old syntax'sall/any/any_of/substitutes. They run against 8 groups of bad inputs, and the rows must match.has:don't change.policy.yamlwith 12 parts, and the "round whose …" subjects narrowingreview_round. All 106 rows of the fixture round's report are identical to the original's, apart from the order of$appliesinputs, which are sorted by their shorter names. pr-reviewer's 131 Rego tests pass. One report takes 0.40 s, against 0.33 s without parts.🤖 Generated with Claude Code