Skip to content

fix(lock): close-lock gives reusable-workflow records their called workflow's uses: - #1247

Merged
hyperpolymath merged 3 commits into
mainfrom
claude/new-session-8bfbi9-close-lock-reusable-uses
Oct 14, 2026
Merged

hyperpolymath merged 3 commits into
mainfrom
claude/new-session-8bfbi9-close-lock-reusable-uses

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

The defect

scripts/close-lock.sh writes every record it adds as a leaf: ref, commit, owner and repo IDs, and no nested uses:. For an action that is correct. For a job-level reusable workflow ref it is not.

Measured on hyperpolymath/palimpsest-license#177 (2026-10-14). The lock was built by this chain (gh actions-lock v0.1.6 → relock-sha-keys → complete-job-refs → close-lock → prune-stale). It listed hyperpolymath/standards@<sha> under each reusable caller, with the leaf records close-lock wrote. On that commit:

  • Governance, Hypatia Security Scan and Secret Scanner all ended in startup_failure, with no jobs.
  • Every workflow that uses only step-level actions started normally.
  • With the caller entries changed to [] and no standards records, all three started.

The gate didn't catch any of this: update-actions-lock.sh --verify-local and the networked --verify both reported the leaf-record lock valid.

What a working lock looks like

I compared locks whose reusable callers do start: hyperpolymath/my-lang (Governance runs, with referenced_workflows resolved) and metadatastician/burble. In both, the record for a reusable ref carries a nested uses: list. That list is exactly the union of the external uses: of the workflow files the repo calls at that ref:

  • each entry is written as the lock key owner/repo@ref, so a sub-path such as /init is dropped
  • local ./, $/ and docker:// refs are excluded

Checked against my-lang's lock:

Record Called files Record vs union
standards@9e9513b governance-reusable, hypatia-scan-reusable 6 = 6, identical
standards@8435558 mirror, scorecard, secret-scanner, spark-theatre-gate 6 = 6, identical

A reusable can call another one; ci-pipeline.yml calls secret-scanner-reusable and rust-ci-reusable at 571cc73. In that case the inner key appears in the outer record's list, as in cicd-squabbler's lock.

close-lock.sh landed on 2026-10-01 (#1116). Those working locks predate it, and nothing in scripts/ writes nested lists. So any lock the chain builds or rebuilds after a standards pin moves now gets leaf records for its reusable refs. regen-dependabot-locks.sh runs the same chain, and so would an estate-wide propagate-workflow-pins.sh run.

The fix

close-lock.sh now does the following:

  1. Collects every job-level call owner/repo/.github/workflows/<file>@<ref> in the caller's workflows.
  2. Reads each called file at <ref> through the contents API, and follows any reusable calls inside it. Each (key, file) pair is read once, so recursion terminates.
  3. Writes each new reusable record with the union as its nested uses:. The existing passes then close the refs that list names.
  4. Completes reusable records an earlier run left as leaves or short, and reports each one as ~ <key>. Correct records are left byte-identical.
  5. Fails closed. If a called file can't be read (an HTTP error, or a body without a top-level jobs:), it writes no record for that ref, changes no existing record, and exits 3. That is the same contract as an unresolvable ref today, so a leaf is never written where a list is owed.

Action records stay leaves, exactly as before. A reusable that uses no external action also stays a leaf. The comment in complete-job-refs.sh now says what close-lock adds.

Tests

scripts/tests/close-lock-test.sh is offline: its stub now serves planted workflow files. It runs 19 passed, 0 failed, the 8 existing cases plus 11 new ones:

  • A new reusable record gets the union, keyed owner/repo@ref. The sub-path, ./, docker://, quotes and comments are all handled. The listed refs are closed, and a second run is byte-identical.
  • A leaf left by an earlier run is completed and reported, and its refs are closed.
  • A reusable that calls a reusable: the inner record gets its own list.
  • A reusable with no external action stays a leaf.
  • Planted positives:
    • a 404 on the called file gives SKIP, exit 3, and no leaf
    • an existing record is left untouched when its file is unreadable
    • a malformed body (exit 0, no jobs:) gives SKIP and exit 3

Mutants (TARGET= copies), each caught:

Mutant Result
list not written 4 failed
no completion 2 failed
no fail-closed guard 1 failed
no recursion 1 failed
sub-path kept 5 failed

Unchanged suites, run locally:

  • Pass: regen-dependabot-locks (35/35), complete-job-refs (16/16), check-lock-sync (13/13), prune-stale (18/18), relock-sha-keys (11/11).
  • Fail identically on main without this change, and none of them uses close-lock: lock-selfcheck, update-actions-lock and check-actions-lock-gate. These look like missing local tooling.

shellcheck -S warning is clean, and so is git diff --check.

End-to-end result

This commit's close-lock.sh rebuilt the lock on hyperpolymath/palimpsest-license#177 from scratch in CI (run 38544820697). Details are in the comment below.

  • Pass 1 wrote the four hyperpolymath/standards@<sha> records with their nested uses:. Pass 2 closed the 9 actions those lists name. Pass 3 found nothing dangling.
  • On the commit carrying that lock (e55c4c3), Governance, Hypatia Security Scan and Secret Scanner all start, and Governance creates all 15 jobs. On 8f1aff5 the same chain with the old leaf records left all three in startup_failure. Nested uses: is the only difference between the two locks.
  • After main was merged into that PR (878e935), the lock gate, check-lock-sync and every other governance job pass.

Order for the estate

This should merge before any estate-wide propagate-workflow-pins.sh run. A pin bump changes the reusable refs, so with the old close-lock.sh every bumped repo would get leaf records, and its Governance, Hypatia and Secret Scanner would stop starting. A startup failure posts no check run, so those repos would look green.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9

…rkflow's uses:

close-lock wrote every record as a leaf. For a job-level reusable call
that is not enough: on hyperpolymath/palimpsest-license#177 (2026-10-14)
a lock listing `hyperpolymath/standards@<sha>` with leaf records made
GitHub refuse Governance, Hypatia Security Scan and Secret Scanner at
startup (startup_failure, no jobs), while every step-only workflow ran.

In the estate locks whose reusable callers do start (my-lang, burble),
that record carries a nested `uses:` equal to the union of the external
`uses:` of the workflow files called at that ref, keyed owner/repo@ref.
close-lock now reads each called file at its ref (transitively, for a
reusable that calls another), writes that list on new records, completes
records an earlier run left as leaves, and fails closed (SKIP, exit 3,
nothing written or changed) when a called file cannot be read.

Tests: 11 new cases in close-lock-test.sh, including planted 404 and
malformed bodies; five mutants (no list, no completion, no fail-closed
guard, no recursion, no sub-path strip) are each caught.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 35 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 88824ad2-827c-4e31-a423-0a6df9cb9197
📥 Commits

Reviewing files that changed from the base of the PR and between c11c255 and d9e2957.

📒 Files selected for processing: 3
  • scripts/close-lock.sh
  • scripts/complete-job-refs.sh
  • scripts/tests/close-lock-test.sh
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

K9 contract conformance

run https://github.com/hyperpolymath/standards/actions/runs/38544883820

K9 normative contract typecheck

k9_contract.ncl typechecks

K9 contract self-test

== the bash mirrors cannot drift from the normative contract ==
ok   leash_levels mirrors k9_contract.ncl
ok   core_capabilities mirrors k9_contract.ncl
ok   contract_version mirrors k9_contract.ncl
ok   schema_major mirrors k9_contract.ncl
== capability arithmetic (§8) ==
ok   capability_ok fs.read accepted
ok   capability_ok rollback.apply accepted
ok   capability_ok x-acme.gpu.alloc accepted
ok   capability_ok x-acme rejected
ok   capability_ok x-.gpu rejected
ok   capability_ok fs.delete rejected
ok   capability_ok  rejected
== the extractor ==
ok   extracts pedigree.security.leash
ok   extracts pedigree.component_type
ok   extracts pedigree.metadata.name
ok   pedigree leash is not reported as top-level leash
ok   required_capabilities for a quiet component
ok   required_capabilities follows allow_network
== the envelope strip keeps line numbers (§3.6) ==
ok   line 1 becomes a comment
ok   line count is preserved
ok   schema_version stays on line 5
== L3: signature presence is not verification (§10) ==
ok   no verifier -> K9-C001 is SKIPPED, never a pass
ok   the skip states presence does not authorise 'Hunt
ok   verifier accepts -> verdict 'Verified, no K9-C001 finding
ok   verifier refuses -> K9-C001 error, verdict 'Rejected
== the fixture runner's attribution cannot be fooled by a filename ==
ok   every extracted finding is well-formed rule+layer
ok   the rule that really fired is attributed
ok   a rule named only in the filename is NOT attributed
ok   K9-C001 is present as a skipped finding
ok   and that same finding is NOT extractable as a rejection
== the dialect discriminator agrees with the coordination grammar (§4.3) ==
ok   magic file opening '---' is coordination
ok   magic file opening 'metadata:' is coordination
ok   plain file opening '---' is unclaimed
ok   plain file opening 'metadata:' is unclaimed
== no Nickel reserved word is used as an identifier ==
ok   the contract and all 27 fixtures avoid Nickel's reserved words

self-test: all assertions passed

K9 conformance fixtures

== positive controls (must pass) ==
ok   extension-capability.k9.ncl
ok   extension-fields.k9.ncl
ok   hunt-fully-granted.k9.ncl
ok   kennel-data.k9.ncl
ok   library-base.ncl
ok   yard-typed-config.k9.ncl

== negative controls (must fail, by the named rule) ==
ok   L0-K9-E001-bad-magic.k9.ncl (rejected by K9-E001 at L0)
ok   L0-K9-E002-nul-byte.k9.ncl (rejected by K9-E002 at L0)
ok   L0-K9-E003-crlf.k9.ncl (rejected by K9-E003 at L0)
ok   L0-K9-E004-no-spdx.k9.ncl (rejected by K9-E004 at L0)
ok   L0-K9-E005-unclaimed-body.k9.ncl (rejected by K9-E005 at L0)
ok   L0-K9-S012-library-with-pedigree.ncl (rejected by K9-S012 at L0)
ok   L0-K9-S014-stray-leash.ncl (rejected by K9-S014 at L0)
ok   L1-K9-S001-no-pedigree.k9.ncl (rejected by K9-S001 at L1)
ok   L1-K9-S002-wrong-major.k9.ncl (rejected by K9-S002 at L1)
ok   L1-K9-S003-todo-component-type.k9.ncl (rejected by K9-S003 at L1)
ok   L1-K9-S004-unknown-leash.k9.ncl (rejected by K9-S004 at L1)
ok   L1-K9-S005-missing-name.k9.ncl (rejected by K9-S005 at L1)
ok   L1-K9-S006-unknown-capability.k9.ncl (rejected by K9-S006 at L1)
ok   L1-K9-S007-ungranted-flag.k9.ncl (rejected by K9-S007 at L1)
ok   L1-K9-S008-hunt-signature-not-required.k9.ncl (rejected by K9-S008 at L1)
ok   L1-K9-S009-hunt-no-signature-block.k9.ncl (rejected by K9-S009 at L1)
ok   L1-K9-S010-hunt-empty-side-effects.k9.ncl (rejected by K9-S010 at L1)
ok   L1-K9-S011-recipes-at-yard.k9.ncl (rejected by K9-S011 at L1)
ok   L1-K9-S013-dangling-import.k9.ncl (rejected by K9-S013 at L1)
ok   L2-K9-N001-two-segment-version.k9.ncl (rejected by K9-N001 at L2)
ok   L2-K9-N001-wrong-field-type.k9.ncl (rejected by K9-N001 at L2)

fixtures: 6 positive, 21 negative (0 needing nickel), 0 failure(s)

K9 corpus conformance (L2)

[validate-k9] 14 conforming, 0 grandfathered (layer all, contract v1.0.0)

hyperpolymath pushed a commit to hyperpolymath/palimpsest-license that referenced this pull request Oct 14, 2026
Rebuilt in CI with the estate chain and standards close-lock 23e258b
(hyperpolymath/standards#1247): each hyperpolymath/standards@<sha> record
now lists the external uses: of the workflows called at that ref, the
shape the estate's working locks have, instead of the [] caller entries.

The governance gate at standards b26d3fb (gh-actions-lock v0.1.6) and
check-lock-sync both pass; the workflow files are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9
@hyperpolymath
hyperpolymath marked this pull request as ready for review October 14, 2026 09:48

Copy link
Copy Markdown
Owner Author

Result from a real lock. This branch's close-lock.sh (23e258b) passes the end-to-end test on hyperpolymath/palimpsest-license#177.

The lock was rebuilt from scratch in CI (palimpsest-license run 38544820697) with gh actions-lock v0.1.6, then relock-sha-keys, complete-job-refs, this close-lock, and prune-stale:

  • Pass 1 wrote the four hyperpolymath/standards@<sha> records, each with its nested uses:. The b26d3fb record is exactly the 4 external actions of governance-reusable.yml@b26d3fb, which I checked against an independent local computation.
  • Pass 2 closed the 9 actions those lists name. Pass 3 found 0 dangling refs.
  • The governance gate at b26d3fb (v0.1.6, run as governance runs it) exited 0. check-lock-sync.sh exited 0, and so did the networked gh actions-lock --verify.
  • No workflow file changed.

On the commit carrying that lock (palimpsest-license e55c4c3), Governance, Hypatia Security Scan and Secret Scanner all start: each resolves its referenced_workflows, and Governance creates all 15 jobs.

On 8f1aff5, the same chain produced the same caller entries but with the old leaf records, and all three ended in startup_failure. The only difference between the two locks is the nested uses: on the reusable records.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

@coderabbitai review


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

Copy link
Copy Markdown
Contributor

K9 contract conformance

run https://github.com/hyperpolymath/standards/actions/runs/38548163250

K9 normative contract typecheck

k9_contract.ncl typechecks

K9 contract self-test

== the bash mirrors cannot drift from the normative contract ==
ok   leash_levels mirrors k9_contract.ncl
ok   core_capabilities mirrors k9_contract.ncl
ok   contract_version mirrors k9_contract.ncl
ok   schema_major mirrors k9_contract.ncl
== capability arithmetic (§8) ==
ok   capability_ok fs.read accepted
ok   capability_ok rollback.apply accepted
ok   capability_ok x-acme.gpu.alloc accepted
ok   capability_ok x-acme rejected
ok   capability_ok x-.gpu rejected
ok   capability_ok fs.delete rejected
ok   capability_ok  rejected
== the extractor ==
ok   extracts pedigree.security.leash
ok   extracts pedigree.component_type
ok   extracts pedigree.metadata.name
ok   pedigree leash is not reported as top-level leash
ok   required_capabilities for a quiet component
ok   required_capabilities follows allow_network
== the envelope strip keeps line numbers (§3.6) ==
ok   line 1 becomes a comment
ok   line count is preserved
ok   schema_version stays on line 5
== L3: signature presence is not verification (§10) ==
ok   no verifier -> K9-C001 is SKIPPED, never a pass
ok   the skip states presence does not authorise 'Hunt
ok   verifier accepts -> verdict 'Verified, no K9-C001 finding
ok   verifier refuses -> K9-C001 error, verdict 'Rejected
== the fixture runner's attribution cannot be fooled by a filename ==
ok   every extracted finding is well-formed rule+layer
ok   the rule that really fired is attributed
ok   a rule named only in the filename is NOT attributed
ok   K9-C001 is present as a skipped finding
ok   and that same finding is NOT extractable as a rejection
== the dialect discriminator agrees with the coordination grammar (§4.3) ==
ok   magic file opening '---' is coordination
ok   magic file opening 'metadata:' is coordination
ok   plain file opening '---' is unclaimed
ok   plain file opening 'metadata:' is unclaimed
== no Nickel reserved word is used as an identifier ==
ok   the contract and all 27 fixtures avoid Nickel's reserved words

self-test: all assertions passed

K9 conformance fixtures

== positive controls (must pass) ==
ok   extension-capability.k9.ncl
ok   extension-fields.k9.ncl
ok   hunt-fully-granted.k9.ncl
ok   kennel-data.k9.ncl
ok   library-base.ncl
ok   yard-typed-config.k9.ncl

== negative controls (must fail, by the named rule) ==
ok   L0-K9-E001-bad-magic.k9.ncl (rejected by K9-E001 at L0)
ok   L0-K9-E002-nul-byte.k9.ncl (rejected by K9-E002 at L0)
ok   L0-K9-E003-crlf.k9.ncl (rejected by K9-E003 at L0)
ok   L0-K9-E004-no-spdx.k9.ncl (rejected by K9-E004 at L0)
ok   L0-K9-E005-unclaimed-body.k9.ncl (rejected by K9-E005 at L0)
ok   L0-K9-S012-library-with-pedigree.ncl (rejected by K9-S012 at L0)
ok   L0-K9-S014-stray-leash.ncl (rejected by K9-S014 at L0)
ok   L1-K9-S001-no-pedigree.k9.ncl (rejected by K9-S001 at L1)
ok   L1-K9-S002-wrong-major.k9.ncl (rejected by K9-S002 at L1)
ok   L1-K9-S003-todo-component-type.k9.ncl (rejected by K9-S003 at L1)
ok   L1-K9-S004-unknown-leash.k9.ncl (rejected by K9-S004 at L1)
ok   L1-K9-S005-missing-name.k9.ncl (rejected by K9-S005 at L1)
ok   L1-K9-S006-unknown-capability.k9.ncl (rejected by K9-S006 at L1)
ok   L1-K9-S007-ungranted-flag.k9.ncl (rejected by K9-S007 at L1)
ok   L1-K9-S008-hunt-signature-not-required.k9.ncl (rejected by K9-S008 at L1)
ok   L1-K9-S009-hunt-no-signature-block.k9.ncl (rejected by K9-S009 at L1)
ok   L1-K9-S010-hunt-empty-side-effects.k9.ncl (rejected by K9-S010 at L1)
ok   L1-K9-S011-recipes-at-yard.k9.ncl (rejected by K9-S011 at L1)
ok   L1-K9-S013-dangling-import.k9.ncl (rejected by K9-S013 at L1)
ok   L2-K9-N001-two-segment-version.k9.ncl (rejected by K9-N001 at L2)
ok   L2-K9-N001-wrong-field-type.k9.ncl (rejected by K9-N001 at L2)

fixtures: 6 positive, 21 negative (0 needing nickel), 0 failure(s)

K9 corpus conformance (L2)

[validate-k9] 14 conforming, 0 grandfathered (layer all, contract v1.0.0)

@github-actions

Copy link
Copy Markdown
Contributor

K9 contract conformance

run https://github.com/hyperpolymath/standards/actions/runs/38548532360

K9 normative contract typecheck

k9_contract.ncl typechecks

K9 contract self-test

== the bash mirrors cannot drift from the normative contract ==
ok   leash_levels mirrors k9_contract.ncl
ok   core_capabilities mirrors k9_contract.ncl
ok   contract_version mirrors k9_contract.ncl
ok   schema_major mirrors k9_contract.ncl
== capability arithmetic (§8) ==
ok   capability_ok fs.read accepted
ok   capability_ok rollback.apply accepted
ok   capability_ok x-acme.gpu.alloc accepted
ok   capability_ok x-acme rejected
ok   capability_ok x-.gpu rejected
ok   capability_ok fs.delete rejected
ok   capability_ok  rejected
== the extractor ==
ok   extracts pedigree.security.leash
ok   extracts pedigree.component_type
ok   extracts pedigree.metadata.name
ok   pedigree leash is not reported as top-level leash
ok   required_capabilities for a quiet component
ok   required_capabilities follows allow_network
== the envelope strip keeps line numbers (§3.6) ==
ok   line 1 becomes a comment
ok   line count is preserved
ok   schema_version stays on line 5
== L3: signature presence is not verification (§10) ==
ok   no verifier -> K9-C001 is SKIPPED, never a pass
ok   the skip states presence does not authorise 'Hunt
ok   verifier accepts -> verdict 'Verified, no K9-C001 finding
ok   verifier refuses -> K9-C001 error, verdict 'Rejected
== the fixture runner's attribution cannot be fooled by a filename ==
ok   every extracted finding is well-formed rule+layer
ok   the rule that really fired is attributed
ok   a rule named only in the filename is NOT attributed
ok   K9-C001 is present as a skipped finding
ok   and that same finding is NOT extractable as a rejection
== the dialect discriminator agrees with the coordination grammar (§4.3) ==
ok   magic file opening '---' is coordination
ok   magic file opening 'metadata:' is coordination
ok   plain file opening '---' is unclaimed
ok   plain file opening 'metadata:' is unclaimed
== no Nickel reserved word is used as an identifier ==
ok   the contract and all 27 fixtures avoid Nickel's reserved words

self-test: all assertions passed

K9 conformance fixtures

== positive controls (must pass) ==
ok   extension-capability.k9.ncl
ok   extension-fields.k9.ncl
ok   hunt-fully-granted.k9.ncl
ok   kennel-data.k9.ncl
ok   library-base.ncl
ok   yard-typed-config.k9.ncl

== negative controls (must fail, by the named rule) ==
ok   L0-K9-E001-bad-magic.k9.ncl (rejected by K9-E001 at L0)
ok   L0-K9-E002-nul-byte.k9.ncl (rejected by K9-E002 at L0)
ok   L0-K9-E003-crlf.k9.ncl (rejected by K9-E003 at L0)
ok   L0-K9-E004-no-spdx.k9.ncl (rejected by K9-E004 at L0)
ok   L0-K9-E005-unclaimed-body.k9.ncl (rejected by K9-E005 at L0)
ok   L0-K9-S012-library-with-pedigree.ncl (rejected by K9-S012 at L0)
ok   L0-K9-S014-stray-leash.ncl (rejected by K9-S014 at L0)
ok   L1-K9-S001-no-pedigree.k9.ncl (rejected by K9-S001 at L1)
ok   L1-K9-S002-wrong-major.k9.ncl (rejected by K9-S002 at L1)
ok   L1-K9-S003-todo-component-type.k9.ncl (rejected by K9-S003 at L1)
ok   L1-K9-S004-unknown-leash.k9.ncl (rejected by K9-S004 at L1)
ok   L1-K9-S005-missing-name.k9.ncl (rejected by K9-S005 at L1)
ok   L1-K9-S006-unknown-capability.k9.ncl (rejected by K9-S006 at L1)
ok   L1-K9-S007-ungranted-flag.k9.ncl (rejected by K9-S007 at L1)
ok   L1-K9-S008-hunt-signature-not-required.k9.ncl (rejected by K9-S008 at L1)
ok   L1-K9-S009-hunt-no-signature-block.k9.ncl (rejected by K9-S009 at L1)
ok   L1-K9-S010-hunt-empty-side-effects.k9.ncl (rejected by K9-S010 at L1)
ok   L1-K9-S011-recipes-at-yard.k9.ncl (rejected by K9-S011 at L1)
ok   L1-K9-S013-dangling-import.k9.ncl (rejected by K9-S013 at L1)
ok   L2-K9-N001-two-segment-version.k9.ncl (rejected by K9-N001 at L2)
ok   L2-K9-N001-wrong-field-type.k9.ncl (rejected by K9-N001 at L2)

fixtures: 6 positive, 21 negative (0 needing nickel), 0 failure(s)

K9 corpus conformance (L2)

[validate-k9] 14 conforming, 0 grandfathered (layer all, contract v1.0.0)

@sonarqubecloud

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath merged commit 2ae085c into main Oct 14, 2026
65 checks passed
@hyperpolymath
hyperpolymath deleted the claude/new-session-8bfbi9-close-lock-reusable-uses branch October 14, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants