Skip to content

docs(args-contract): correct two audit findings that keyword-rosetta had already settled - #2788

Merged
squid-protocol merged 1 commit into
mainfrom
fix/2773-followup-contract-audit-corrections
Sep 6, 2026
Merged

docs(args-contract): correct two audit findings that keyword-rosetta had already settled#2788
squid-protocol merged 1 commit into
mainfrom
fix/2773-followup-contract-audit-corrections

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Follow-up to #2773 / #2786, and a correction to my own work in it.

The 46-language audit in docs/args_rule_contract.md reported four contract violations and filed four issues. Two of them were already triaged in keyword-rosetta's deviation_ledger.json — the corpus's audit trail of exactly these questions — and I did not check it before filing. Both are corrected here.

haskell — inside the contract, not outside it

haskell-caf-bindings-count-as-functions (engine-semantic, validated 2026-09-04):

Top-level value bindings (CAFs like region = unsafePerformIO ...) count func_start/args like any function binding — morphologically correct for haskell, where top-level values ARE nullary functions.

That reading is better than the one I filed. In Haskell a top-level value genuinely is a nullary function, and the engine is consistent about it: func_start counts the same binding, and _args_arrow_count_groups correctly derives arity 0 from the arrow-less type. The narrowing I proposed (require a top-level ->) would have made args and func_start disagree on the same binding — worse than the thing it fixed. #2785 closed as not-planned.

m4 — the headline number is intended morphology; a narrower thing survives

m4-parameters-are-use-sites (intended-morphology, validated 2026-09-04):

m4 macros have no parameter list [...] $1 inside the body IS the parameter, so the rule counts one arg per USE, not per declaration [...] equalising it would mean writing macros that never reference their own argument.

So the +38% file-level figure is not a defect, and m4 owes no re-bless. What the ledger does not cover is avg_func_args, which is an arity: m4_define(probe_test, [AT_SETUP($1) AT_CHECK($1)]) is one parameter referenced twice, and reads 2, because m4 lacks the _args_findall_max_groups helper shell uses for the identical morphology. #2784 rescoped and retitled to that.

Unchanged

groovy (#2782) and apex (#2783) stand — genuine call-site counting from a member arm whose return-type prefix can match zero times. keyword-rosetta now carries them as args-call-site-counting-apex-groovy, split out of ts-callparen-args when #2786 retired that entry's typescript and objective-c arms (corpus PR pairing this one).

What changed in the doc

  • The haskell and m4 audit rows, and corollary 3 — which now says what the ledger established: at file level a positional reference count is the language's own morphology; it is avg_func_args where counting references rather than distinct positions is wrong.
  • The findings section, which now records both corrections rather than quietly dropping them.
  • A new entry in "Notes for the next rule": check the ledger before calling a language's args a defect. grep '\"signal\": \"args\"' deviation_ledger.json is a 30-second check that would have caught both of these, and it outranks any amount of fresh measurement.

Docs only — no engine or test changes, no golden-master impact.

🤖 Generated with Claude Code

…had already settled

Follow-up to #2773 / #2786. The 46-language audit in `docs/args_rule_contract.md` reported
four contract violations. Two of them were already triaged in keyword-rosetta's
`deviation_ledger.json`, and checking it first would have avoided re-litigating them.

* `haskell` is INSIDE the contract, not narrowly outside it.
  `haskell-caf-bindings-count-as-functions` (engine-semantic, validated 2026-09-04) reads an
  arrow-less `::` signature as a CAF, and a Haskell top-level value genuinely is a nullary
  function. The engine is consistent: `func_start` counts it too and
  `_args_arrow_count_groups` derives arity 0. The narrowing the audit proposed would have made
  `args` and `func_start` disagree on the same binding. #2785 closed as not-planned.
* `m4`'s FILE-LEVEL count is intended morphology (`m4-parameters-are-use-sites`): a macro names
  no parameters, so `$1` in the body IS the parameter, and equalising it would mean writing
  macros that never reference their own argument. What survives is narrower and untouched by
  that verdict -- `avg_func_args` has no `_args_findall_max_groups`, so `AT_SETUP($1)
  AT_CHECK($1)` reads arity 2 for a one-parameter macro. #2784 rescoped to that.

`groovy` (#2782) and `apex` (#2783) stand unchanged; keyword-rosetta now carries them as
`args-call-site-counting-apex-groovy`, split out of `ts-callparen-args` when this fix retired
that entry's typescript and objective-c arms.

Corollary 3 is reworded to say what the ledger established: at file level a positional
reference count is the language's morphology, and it is `avg_func_args` -- an arity -- where
counting references instead of distinct positions is wrong. Adds "check the ledger first" to
the notes for the next rule, since that is the reusable lesson here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

@squid-protocol
squid-protocol merged commit b85e771 into main Sep 6, 2026
3 checks passed
@squid-protocol
squid-protocol deleted the fix/2773-followup-contract-audit-corrections branch September 6, 2026 02:13
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