Skip to content

feat(deed): bun port of deed_lint + reusable deed-conformance gate - #1164

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/deed-lint-bun-20261006
Oct 6, 2026
Merged

hyperpolymath merged 1 commit into
mainfrom
feat/deed-lint-bun-20261006

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Summary

Ports the DEED validator 1-formats/deed/tools/deed_lint.py to bun (deed_lint.js, zero dependencies) and makes deed-conformance.yml a reusable gate (workflow_call). Other estate repos can then lint their .deed files without Python, which the estate bans. This is the shim echidna needs before its .a2ml → .deed rename (standards#837 lane).

  • deed_lint.js follows the grammar spec/abnf/deed.abnf v1.0.0 and prints exactly what the Python prints (OK <file> / FAIL <file>: line N: <msg>, rc=1 on any failure).
  • deed-conformance.yml changes:
    • In this repo it runs the bun self-test, bun test, the fixture corpus, a python/bun parity step, and a lint of every committed deed.
    • As a reusable it checks out the linter at job.workflow_sha (sparse, persist-credentials: false), so a caller pinned to a standards SHA gets exactly that linter.
    • The optional input require-files makes a zero-deed caller fail instead of pass.
  • deed_lint.py stays, because a2ml_to_deed.py imports it in-process. The parity step fails on any byte of difference between the two outputs over every committed .deed, invalid fixtures included, so the two cannot drift while both exist.

No issue to close (campaign: standards#837).

Type of change

  • 🐛 Bug fix — no; nothing in the existing linter changes
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change — no; push/pull_request behaviour keeps the same three gates, now run under bun
  • 🕳️ Soundness fix — no
  • 📖 Documentation (1-formats/deed/tools/README.adoc)
  • 🧹 Refactor / tech debt — no
  • ⚡ Performance — no
  • 🔧 Build / CI / tooling

📌 New pins

  • Head SHA: 1c99565112d054520374bfac2bf53ff44e4a8e9c
  • oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 (v2.2.0). Already in actions.lock for ci-pipeline.yml; this PR only adds it to the deed-conformance.yml workflow entry.
  • actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 (v7.0.1). Unchanged; now used twice in the workflow.
  • No lockfile, container or other pin changes.

How has this been verified?

  • bun test 1-formats/deed/tools/ → 53 pass / 0 fail, 84 expect() calls.
  • bun deed_lint.js --self-test → SELF-TEST OK. --fixtures fixtures → FIXTURES OK (9 valid pass, 10 invalid fail).
  • Every committed deed (the workflow's own find) → all OK, rc=0.
  • Mutation check: removing the tab rule turned 2 tests red, removing the bare-true/false rule 4, and removing the schema-version-once rule 3.
  • Lock:
    • .githooks/validate-actions-lock.sh → ✅ 26/26.
    • scripts/check-lock-sync.sh → rc=0.
    • The lock was regenerated in a scratch copy (gh actions-lock --no-narrow --no-migrate-local-actions --no-interactive). Its only deed-related difference was the one setup-bun line, applied by hand.
    • gh actions-lock --no-fix --verify → 1 error, in signed-push-smoke.yml (a local-path action). It is present on main and unrelated to this PR; 0 errors are in deed-conformance.yml.
  • Python/bun parity: not run locally (Python is not run on this machine). In CI (lint job on 1c0ff6d) the parity step passed: byte-identical, 20 lines each over every committed deed.
  • CodeFactor flagged lexValue as a Complex Method. 1c99565 splits it into lexHashForm / lexList / lexQuoted / lexIntegerToken. Tests, self-test and fixtures are unchanged, and output over all 20 committed deeds is byte-identical before and after.

Checklist

  • My commits are signed (git commit -S).
  • I ran the project's own checks/tests locally and they pass. The pre-commit suite passed. Its JS lint gate reported the 2 new .js files as not checked (no pinned bun lint gate exists), which is a skip, not a pass.
  • New files carry the correct SPDX identifier (MPL-2.0 on both .js files); no existing file was relicensed.
  • Docs updated. The README now names the bun linter as the CI gate and says why the Python one remains.
  • No soundness hole introduced. The deliberate divergences from the Python are listed below, and the parity step makes any behavioural one visible.

Pre-existing reds (deferred, AGENTS.md §5c item 3)

Each of these is red on main cfc3a92 as well and is not touched by this PR:

Notes for reviewers

Rulings taken in the port, where the JS deliberately differs from the Python:

  1. It accepts a final ) with no trailing newline. The Python crashes there (L246-250) instead of reporting.
  2. Digits are ASCII-only (Python str.isdigit also accepts Unicode digits; the ABNF says DIGIT = %x30-39).
  3. --fixtures with no DIR exits 2 (usage error).
  4. The Python's dead _SELF_TEST and its unreachable encode check were not ported.

None of these changes the output for any committed file; the parity step proves that in CI.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P48P9ErT8UFFeDUfEQiYV7

deed_lint.js is a zero-dependency bun port of deed_lint.py (53 unit
tests incl. the 14-case self-test corpus and all 19 fixtures).
deed-conformance.yml now runs the bun linter, gains a workflow_call
trigger (optional require-files input) so other repos can lint their
.deed files with the linter at this workflow's own commit, and carries
a python/bun parity step that fails on any byte of output difference.

deed_lint.py stays: a2ml_to_deed.py imports it in-process.
actions.lock: add oven-sh/setup-bun@0c5077e5 (v2.2.0, already locked
for ci-pipeline.yml) to the deed-conformance workflow entry.

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

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 88af5c1c-1b54-4059-8bc9-c4876f6ac643
📥 Commits

Reviewing files that changed from the base of the PR and between cfc3a92 and 1c0ff6d.

⛔ Files ignored due to path filters (1)
  • .github/workflows/actions.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • .github/workflows/deed-conformance.yml
  • 1-formats/deed/tools/README.adoc
  • 1-formats/deed/tools/deed_lint.js
  • 1-formats/deed/tools/deed_lint.test.js
 _______________________________________________________________________________________________________
< Start when you're ready. You've been building experience all your life. Don't ignore niggling doubts. >
 -------------------------------------------------------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • 🔴 Error committing to branch - (🔄 Check to retry)
  • Create a new PR
  • Autopilot · 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

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

K9 contract conformance

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

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
== 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
ERROR   K9-N001 [L2] 1-formats/k9/tools/fixtures/valid/extension-fields.k9.ncl: component violates the K9.Component contract: error: contract broken by a value        extra fields `failure_mode_defenses`, `execution`    ┌─ /home/runner/work/standards/standards/1-formats/k9/tools/fixtures/valid/.k9-validate.8784.6134.driver.ncl:3:1    │  3 │ k9_doc | K9.Component 
FAIL extension-fields.k9.ncl should conform (exit 1)
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), 1 failure(s)

@sonarqubecloud

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath merged commit 44a0de4 into main Oct 6, 2026
58 of 69 checks passed
@hyperpolymath
hyperpolymath deleted the feat/deed-lint-bun-20261006 branch October 6, 2026 13:59
@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Add Carrot credits or activate Agent usage billing to use Autopilot

@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

❌ Failed to create Coding Agent finishing-touch task. Please try again.

hyperpolymath added a commit that referenced this pull request Oct 6, 2026
<!--
SPDX-License-Identifier: CC-BY-SA-4.0
-->
## Summary

#1164 moved `deed-conformance.yml` from python to bun, which removed its
inline-python steps. The workflow stayed listed in the shrink-only
ledger `.machine_readable/inline-python-allow.txt`.
`scripts/tests/check-inline-python-test.sh` fails on a stale entry, so
`Repo self-tests` went red on main after #1164. This PR deletes that one
ledger line.

No issue. This is a follow-up to #1164.

## Type of change

- [x] 🐛 Bug fix (non-breaking change that fixes an issue). It removes a
stale ledger entry.
- [ ] ✨ New feature: does not apply, no new behaviour.
- [ ] 💥 Breaking change: does not apply.
- [ ] 🕳️ Soundness fix: does not apply.
- [ ] 📖 Documentation: does not apply.
- [ ] 🧹 Refactor / tech debt: does not apply.
- [ ] ⚡ Performance: does not apply.
- [x] 🔧 Build / CI / tooling. It changes a CI ledger.

## 📌 New pins

Head SHA: **14e738256ed5cde44cb2d2928fa8a0203dadfc2f**

This PR adds or changes no pins: no `uses:` SHAs, no `actions.lock`
entries, no lockfiles, no container digests.

## How has this been verified?

- `bash scripts/tests/check-inline-python-test.sh` on this branch → **24
passed, 0 failed**. On main, the stale entry made this test fail.
- `Repo self-tests` will **still be red** after this PR. Three tests
were already failing on main before #1164: build-registry,
build-scorecards and kyaml-format. Their failure counts are identical on
a clean main worktree. This PR does not touch them, and they are tracked
separately.

## Checklist

- [x] My commits are **signed**: `git log --format=%G?` shows `G` on
14e7382.
- [x] I ran the project's own checks locally. The inline-python ledger
test passes; the three pre-existing failures are described above.
- [ ] New files carry SPDX: does not apply. No new files; one line is
deleted from an existing ledger.
- [x] Docs are updated and no claim overstates. No documentation
describes this ledger entry.
- [x] No soundness hole: the ledger only shrinks, and the test still
rejects any growth.

## Notes for reviewers

This is a one-line deletion. The ledger format is `path:count`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01P48P9ErT8UFFeDUfEQiYV7

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Oct 7, 2026
main already carries the bun port (44a0de4, #1164); keep this branch's
lexValue split of deed_lint.js. 53/53 tests pass; output identical to
main's linter on 41 deed files and fixtures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014BxjiTAaTZCHVWn2U5NWhL
@hyperpolymath hyperpolymath mentioned this pull request Oct 7, 2026
4 of 13 tasks
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.

1 participant