Skip to content

ci(haskell): build every package detect counted, not just root - #1181

Merged
hyperpolymath merged 3 commits into
mainfrom
ci/haskell-build-where-detected
Oct 6, 2026
Merged

hyperpolymath merged 3 commits into
mainfrom
ci/haskell-build-where-detected

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

The Haskell job in the shared ci-pipeline.yml now builds every package that detect counted, not just the repo root.

detect counts *.cabal at any depth: a git pathspec * crosses /. But the job ran cabal build all only at the root. In standards, the only Haskell package is nested at rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/. So Call CI Pipeline / Haskell turned on, found no package at the root, and failed on every push to main. The probe and its consumer were answering different questions.

Owner ruling (2026-10-06, in session): fix it if it is valuable. I took "make the consumer build what the probe counted" over "narrow the probe to the root". Narrowing would have turned main green while silently leaving nested Haskell uncompiled in this repo and in every caller.

New behaviour:

  • Root cabal.project present: used as-is. This is unchanged for every repo that has one.
  • No root cabal.project: the job writes an untracked one listing each directory holding a tracked *.cabal. It uses the same pathspec as the probe. A repo with only a root .cabal gets packages: ./, which builds what it built before.
  • *.hs / stack.yaml but no *.cabal: a named ::error:: saying there is nothing cabal can build. Before, the job died with cabal's own message.

Refs #1161. That issue's Haskell half; its registry-drift half is separate.

Type of change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature: no
  • 💥 Breaking change: not breaking, but estate-visible. A caller with no root cabal.project and nested .cabal files will now compile those packages under -Wall -Werror. A new red there is real code failing, not this change.
  • 🕳️ Soundness fix: arguably yes; it closes a hole where nested Haskell was counted but never compiled. Left unticked because this PR changes no checker or proof.
  • 📖 Documentation: no; the rationale is in a comment beside the step.
  • 🧹 Refactor: no
  • ⚡ Performance: no
  • 🔧 Build / CI / tooling

📌 New pins

  • Head SHA: 49d50162cc58b479ec8bdbe55e239ed8dd5def4b
  • No uses: refs added or changed, no actions.lock change, no lockfile or container digest changes.

How has this been verified?

  • Offline fixtures: I extracted the step's selection logic verbatim and ran it under set -euo pipefail in four throwaway git repos:
    • nested package → generated packages: a/b/pkg/, rc=0;
    • root .cabal → packages: ./, rc=0;
    • .hs only → the named ::error::, rc=1;
    • own cabal.project → used as-is, rc=0.
  • actionlint: 4 findings on origin/main's file, 4 on this branch's, all at lines this PR does not touch, so none added.
  • Pre-commit suite: gitleaks, SPDX, SHA pins, actions-lock coverage, permissions: all passed.
  • End to end: self-ci.yml calls ./.github/workflows/ci-pipeline.yml, so this PR's own Call CI Pipeline / Haskell run exercises the change against the real nested sanctify-php package. Read that check for the result; I have not run cabal locally because no cabal binary is installed here.

Checklist

  • My commits are signed (git commit -S).
  • I ran the project's own checks locally and they pass. That means the pre-commit suite and actionlint, which shows no new findings. The cabal build itself runs only in CI.
  • New files carry the correct SPDX: N/A, no new files. The generated cabal.project is an untracked CI-runtime file.
  • Docs are updated, and no public claim now overstates what the code does. The step's summary line now says which cabal.project was used.
  • I have not introduced a soundness hole. Flagged: a caller whose nested .cabal is a deliberate fixture that must not build would now see it built. The fix for that caller is a root cabal.project listing what it means to build.

Notes for reviewers

  • If sanctify-php itself fails -Wall -Werror, Call CI Pipeline / Haskell on this PR stays red. That would be an honest red about that package's code, not this workflow. In that case I'll list it under deferred checks with an issue, rather than weaken the gate.

Deferred red checks

Filled in from this PR's own run.

🤖 Generated with Claude Code

https://claude.ai/code/session_012kgrMQRhSmZMBbF9Ui1zBw

@coderabbitai

coderabbitai Bot commented Oct 6, 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 56 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: 2cd9431e-1143-4997-99ed-7b21852c7a97
📥 Commits

Reviewing files that changed from the base of the PR and between 2397599 and 5064bdd.

📒 Files selected for processing (2)
  • .github/workflows/ci-pipeline.yml
  • rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/sanctify-php.cabal
  • 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/37529448444

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
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] debt rhodium-standard-repositories/rsr-compliance-checklist.k9.ncl (fail) — K9-N001 K9-S004 K9-S005 K9-S014 (grandfathered; touching it makes it blocking)
[validate-k9] 14 conforming, 1 grandfathered (layer all, contract v1.0.0)

@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/37529708989

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
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] debt rhodium-standard-repositories/rsr-compliance-checklist.k9.ncl (fail) — K9-N001 K9-S004 K9-S005 K9-S014 (grandfathered; touching it makes it blocking)
[validate-k9] 14 conforming, 1 grandfathered (layer all, contract v1.0.0)

@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Add Carrot credits or activate Agent usage billing to use Autopilot

@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 6, 2026 20:54
@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/37530033685

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
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] debt rhodium-standard-repositories/rsr-compliance-checklist.k9.ncl (fail) — K9-N001 K9-S004 K9-S005 K9-S014 (grandfathered; touching it makes it blocking)
[validate-k9] 14 conforming, 1 grandfathered (layer all, contract v1.0.0)

@hyperpolymath
hyperpolymath merged commit ebfcd98 into main Oct 6, 2026
55 of 61 checks passed
@sonarqubecloud

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath deleted the ci/haskell-build-where-detected branch October 6, 2026 20:55
hyperpolymath added a commit that referenced this pull request Oct 6, 2026
…#1185)

## Summary

This resyncs the vendored `sanctify-php` copy
(`rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/`)
from upstream `hyperpolymath/sanctify-php` main **`fa9bd386`**.

Since #1181 the shared Haskell job builds every package that `detect`
counts, so this copy now gets compiled. It cannot even resolve. It held
37 of upstream's 182 files, and its `.cabal` pins `base ^>=4.17` (GHC
9.4) while the job's GHC ships `base-4.22`. Upstream has since relaxed
that bound to `base >=4.17`. Owner ruling (2026-10-06, in session):
resync from upstream, rather than excluding the package or leaving it
red.

The resync is scoped; nothing upstream was copied wholesale:

- **In:** every path the copy already tracked, made identical to
upstream. Paths upstream deleted are deleted here too: 5
ISSUE_TEMPLATEs, `comprehensive-quality.yml`, and `LICENSE.txt`
(upstream ships `LICENSE`). Also added is what the `.cabal` needs to
build: `src/`, `app/`, `bench/`, `test/*.hs` and `LICENSE`.
- **Kept at the old vendored version.** Upstream's copy fails one of
this repo's own gates, and editing vendored content to pass it is not
ours to do. Neither file plays any part in the build.
  - `.github/dependabot.yml`: no SPDX header upstream (validate-spdx).
- `.claude/CLAUDE.md`: upstream still names the retired `6a2/` path
(check-canonical-names).
- **Out:**
- `.machine_readable/`: it holds a retired `6a2/` dir, plus K9
contractiles that would enter this repo's K9 gates.
  - Upstream's 13 newer workflows and `.github/hooks`.
  - `test/fixtures` and `test-plugins`: deliberately vulnerable PHP.
  - `www/` and `docs/`.

The vendored `.hs` and `.cabal` files are upstream code, not written
here. So any docstring-coverage score on them describes upstream.

## Type of change

- [x] 🐛 Bug fix (non-breaking change that fixes an issue): it unblocks
`Call CI Pipeline / Haskell` on main.
- [ ] ✨ New feature: no
- [ ] 💥 Breaking change: no; the vendored copy has no consumers in this
repo.
- [ ] 🕳️ Soundness fix: no checker or proof changes.
- [ ] 📖 Documentation: no
- [ ] 🧹 Refactor: no
- [ ] ⚡ Performance: no
- [x] 🔧 Build / CI / tooling

## 📌 New pins

- Head SHA: **`092806946ca6e87875b032968e0cc3295977cc11`**
- No changes to this repo's own workflow `uses:` refs, its
`actions.lock`, lockfiles or container digests.
- The nested (non-running) vendored workflows now carry upstream's SHA
pins, and every `uses:` in them is a 40-hex SHA. Debtfile
`vendored-mirror-unpinned-actions` falls from 42 to 40.

## How has this been verified?

- **Pre-commit suite:** passed, including gitleaks, SPDX, SHA pins,
actions-lock coverage, K9 ("no K9 files to check") and canonical names.
The Haskell lint gate *skipped*, because neither fourmolu nor hlint is
installed.
- **`scripts/run-debtfile.sh`:**
  - `todo-fixme-markers` holds at 84;
  - `vendored-mirror-unpinned-actions` is paid down from 42 to 40;
- `gate-scripts-without-tests` (33 > 32) and the expired
`shell-scripts-missing-spdx` acceptance are red identically on
`origin/main` `ebfcd98b`, measured in a detached worktree, so they are
not introduced here.
- **`scripts/check-lock-sync.sh` and
`scripts/check-allowed-actions.sh`:** rc=0, both on this tree and on
main.
- **Build:** there is no local cabal, so this PR's own `Call CI Pipeline
/ Haskell` run is the build test. Upstream's own Haskell CI is no
predictor: its last 30 runs were 25 failures, 3 cancellations and 2
startup failures. Its last run that actually built (564bcde3) failed on
a module-name mismatch, which is fixed at `fa9bd386`; upstream main
itself has never been built in CI.

## Checklist

- [x] My commits are **signed** (`git commit -S`).
- [x] I ran the project's own checks locally and they pass. The listed
Debtfile reds are pre-existing on main.
- [x] New files carry the correct SPDX. Every added `.hs` file carries
upstream's own header, unchanged; no licence text or header was edited.
- [x] Docs are updated, and no public claim now overstates what the code
does. This PR changes no docs.
- [x] I have not introduced a soundness hole.

## Notes for reviewers

- If this PR's Haskell run is still red, the cause will be upstream
package code or third-party bounds against the unpinned latest GHC. I
will defer it below with an issue rather than patch sanctify-php inside
standards; code fixes belong upstream.
- Whether standards should vendor this package at all is a separate
question. It is recorded in `dev-notes/inbox/findings.md`, not decided
here.

## Deferred red checks

Filled in once this PR's own run completes.

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

https://claude.ai/code/session_012kgrMQRhSmZMBbF9Ui1zBw

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Oct 6, 2026
## Summary

Corrects the Haskell build step's comment, and its guard's error text,
in `.github/workflows/ci-pipeline.yml`. Since #1184 both describe a
detect probe that no longer exists.

#1181 and #1184 merged opposite answers to #1161:

- #1181 made the build step generate a `cabal.project` for every tracked
package, because detect counted `*.cabal` at any depth.
- #1184, merged after it, narrowed detect to a root `cabal.project` or a
root `*.cabal`. It reports nested-only Haskell as **unsupported**.

On 2026-10-06 the owner ruled that #1184's root-only detect stands. This
PR brings the build step's text into line with that ruling.

Two pieces of text were false on `main`:

- **The comment.** It said the probe "counts `*.cabal` at ANY depth" and
that narrowing it "would have hidden nested Haskell instead".
- **The `::error::` text.** It said "detected (*.hs or stack.yaml)".
Detect no longer counts either.

Closes # (none. This follows up #1161, #1181 and #1184.)

## Type of change

- [ ] 🐛 Bug fix: no behaviour changes.
- [ ] ✨ New feature: none.
- [ ] 💥 Breaking change: no. Comment and message text only.
- [ ] 🕳️ Soundness fix: no checker logic changes. The text it corrects
did misdescribe a gate.
- [x] 📖 Documentation (in-workflow comment and error text)
- [ ] 🧹 Refactor: nothing is restructured.
- [ ] ⚡ Performance: not affected.
- [x] 🔧 Build / CI / tooling (the file is the shared CI pipeline)

## 📌 New pins

Head SHA: **`949302ecfb4568295c36e6a7dfe9317f0a821ba1`**. No pins are
added or changed: no `uses:`, `actions.lock`, lockfile or digest edits.

## How has this been verified?

- `git diff --stat origin/main` → 1 file, comment and `::error::` text
only. The second commit (`949302ec`) takes CodeRabbit's point: a root
`cabal.project` listing only nested packages also turns the job on, so
the step does not always have a root package. Every changed line is a
`#` comment or the quoted `::error::` string.
- `ruby -e 'YAML.load_file(...)'` on the edited workflow parses with rc
0.
- `bash scripts/check-lock-sync.sh` → `actions.lock is in sync`. `bash
scripts/check-allowed-actions.sh` → rc 0.
- I read the new text against `main`'s detect step:
  - L159 is `N_HASKELL=$(count 'cabal.project' ':(glob)*.cabal')`.
- L232–238 probe nested Haskell as unsupported only when `N_HASKELL` is
0.
- So the `else` branch runs only with a root `*.cabal`. It then lists
`.` plus each nested package directory, which is what the new comment
says.

## Checklist

- [x] My commits are **signed** (`git commit -S`). `git log
--format=%G?` → `G`.
- [x] I ran the project's own checks/tests locally and they pass:
lock-sync and allowed-actions. The commit-msg hook accepted the message
with one length warning.
- [ ] New files carry the correct `SPDX-License-Identifier`: no new
files. The existing header is unchanged.
- [x] Docs are updated, and no public claim now overstates what the code
does. That is the whole point of this PR.
- [x] I have not introduced a soundness hole: the logic is untouched.

## Deferred red checks

Both reds already fail on `main` (`7d51f30f`). This PR does not touch
either one:

- `Registry + topology in sync`: deferred to #1161 (registry drift on
main).
- `Repo self-tests`: deferred to #1161. The failing suite is
`build-registry-test.sh`, which reports `FAIL: repository ledger
drifted`. That is the same drift.

## Notes for reviewers

- On `main`, standards' own Haskell is now skipped and listed as
unsupported. So the vendored sanctify-php (#1185) is not built here.
- Upstream sanctify-php `main` also does not compile:
`src/Sanctify/Parser.hs` line 6 is `//! verified alternatives.`. A
separate one-line upstream fix PR is being opened. Re-syncing this copy
afterwards is a later step.

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

https://claude.ai/code/session_012kgrMQRhSmZMBbF9Ui1zBw

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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