Skip to content

feat: add lychee offline module and CI lane - #11

Merged
kyle-sexton merged 1 commit into
mainfrom
feat/lychee-module
Jun 22, 2026
Merged

feat: add lychee offline module and CI lane#11
kyle-sexton merged 1 commit into
mainfrom
feat/lychee-module

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Add the lychee module — a decoupled lychee.toml (full fragment checking +
repo-agnostic path excludes), good/bad fixtures, and lychee.test.sh on the
shell harness. Wire a standards ci.yml lychee lane (the ci-workflows
lychee-offline composite action, SHA-pinned) that runs --offline so only local
file links and #anchors are checked — deterministic — plus a local
lychee-fixtures job, both folded into ci-status; bump all action pins to the
same ci-workflows commit.

Broaden the markdown self-lint exclusion to fixtures/*/bad so intentionally
broken fixtures (e.g. lychee's bad anchor, which markdownlint MD051 also flags)
are not linted by sibling tools.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Add the lychee module — a decoupled lychee.toml (full fragment checking +
repo-agnostic path excludes), good/bad fixtures, and lychee.test.sh on the
shell harness. Wire a standards ci.yml lychee lane (the ci-workflows
lychee-offline composite action, SHA-pinned) that runs --offline so only local
file links and #anchors are checked — deterministic — plus a local
lychee-fixtures job, both folded into ci-status; bump all action pins to the
same ci-workflows commit.

Broaden the markdown self-lint exclusion to fixtures/*/bad so intentionally
broken fixtures (e.g. lychee's bad anchor, which markdownlint MD051 also flags)
are not linted by sibling tools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kyle-sexton
kyle-sexton merged commit cf9d580 into main Jun 22, 2026
27 checks passed
@kyle-sexton
kyle-sexton deleted the feat/lychee-module branch June 22, 2026 19:36
kyle-sexton added a commit that referenced this pull request Jul 8, 2026
## Problem
The `owner/repo#N` tracker-reference rule let the **owner** segment
contain `.`, so a bare domain with a numeric fragment in a comment —
e.g. `// see foo.com/bar#3` or `# example.com/page#2` at a space/start
boundary — was misread as a cross-repo issue reference and flagged. The
existing leading-boundary `.`/`-` exclusion only caught hosts *embedded*
in a longer URL (preceded by `/` or `.`, e.g.
`https://example.com/page#2`), not hosts at a word boundary — so the
adjacent comment's claim that dotted hosts were handled was only half
true.

## Fix
A GitHub **owner** login (user or org) may contain only alphanumerics
and hyphens — never a `.` or `_` (GitHub username rules; ≤39 chars, no
leading/trailing/double hyphen). So the owner character class is
restricted from `[A-Za-z0-9._-]` to `[A-Za-z0-9-]`. The **repo** segment
keeps `.`/`_` because repository names legitimately allow them. A dotted
host can no longer be read as an owner.

Verified against the module test suite (`comment-hygiene.test.sh`),
which I extended: the regression guard now covers **bare** domains
(`foo.com/bar#3`, `example.com/page#2`, `sub.example.com/path#9`)
alongside the existing scheme'd-URL cases. Genuine refs — including
hyphenated owners (`melodic-software/app#123`, `owner-name/repo#7`) —
still match.

- `shellcheck -x`: clean.
- Module test: **12/12 pass** (test #11 now guards the bare-domain false
positive; #12 confirms hyphenated owners still flag).

## Propagation
This library is vendored downstream:
- **ci-workflows** carries a byte-identical copy (its comment-hygiene
action self-test sources it) — a sync PR follows.
- Consuming repos (e.g. `kyle-sexton/github-iac`) re-copy on their next
standards sync.

## Separate follow-up (not fixed here)
While committing I found the **local lefthook `shellcheck` hook diverges
from CI**: CI passes `--rcfile modules/shellcheck/.shellcheckrc` (which
sets `external-sources=true`), but the local hook relies on root
`.shellcheckrc` auto-discovery, and standards has no root copy — so the
hook emits `SC1091` for any script that `source`s another (e.g.
`comment-hygiene.test.sh`) and can't be committed without
`SHELLCHECK_OPTS=--external-sources`. That's a pre-existing dogfooding
gap in standards' own tooling, orthogonal to this fix, and touches the
root-stub/sync-manifest model — flagging for a maintainer decision
rather than fixing inline.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Changes are limited to comment-scan regex behavior and ShellCheck
config; no runtime auth, data, or production paths.
> 
> **Overview**
> **Comment-hygiene** tightens the `owner/repo#N` tracker rule so dotted
hosts in comments (e.g. `foo.com/bar#3`, `example.com/page#2`) are no
longer treated as cross-repo issue refs. The **owner** segment no longer
allows `.` (GitHub logins cannot contain dots); the **repo** segment
still allows `.` and `_`, and `_` remains in the owner class for GitHub
Enterprise Managed User logins (e.g. `mona-cat_octo/repo#12`). Tests add
bare-domain regression cases and an EMU owner positive case.
> 
> A **root `.shellcheckrc`** is added as the repo’s ShellCheck ruleset
(aligned with `modules/shellcheck/`), so local hooks that auto-discover
config from the repo root can resolve `source`d scripts with
`external-sources=true` and the same optional checks as CI’s `--rcfile`
path.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
76df493. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 15, 2026
…on governance (#123)

## Summary

Closes decisions **#27**, **#63**, and **#65** from the [Decisions
Log](https://claude.ai/code/artifact/232ecdce-8316-4880-8c0a-dc3c7dcf3a63)
(evidence/rationale:
https://claude.ai/code/artifact/3160ae0e-c02f-4619-8de3-60d73faa1100).

### #63 metadata-standards-copy-vs-cite-doctrine

Decision: **keep the "copy" adoption path, require back-link +
drift-check.**

Adds `distribution/governance-process.md`. `conventions/README.md`
already documents two adoption paths for reasoning-only prose — copy
into the consumer's tree, or point at this repo. The copy path stays
available (prose has no runtime coupling to enforce reconciliation the
way `sync-manifest.yml` does), but a copy now carries two mandatory
requirements:

- **Back-link** — every copied file cites its exact canonical source
(repo + path, inline header where the format allows it), using the same
stable-anchor citation discipline `reference-dont-duplicate.md` already
prescribes for the "Expose" file role.
- **Drift-check** — the adopting repo owns a periodic diff of its copy
against the current canonical source, with a named owner and trigger,
mirroring the recheck-trigger discipline
`documentation-and-citations.md` already requires for time-bound
external claims.

The doc is explicit that this is distinct from a `managed`
`sync-manifest.yml` component, which already reconciles automatically
and deliberately carries no downstream receipt — the
back-link/drift-check burden applies only where nothing else keeps a
copy current.

### #65 naming-cross-doc-reconciliation-process-ownership

Decision: **establish a standing cross-reference review step for
normative-doc changes.**

Same doc adds the standing process step: before a change to a normative
doc (`naming.md`, `process/issue-tracker.md`, `review/code-quality.md`,
and any other file in the catalog stating a rule another doc cites or
assumes) merges, a cross-reference check confirms no other doc now
contradicts it.

Ownership is named explicitly rather than left implicit:
`required_approving_review_count` stays at `0` org-wide (decision #11,
single-maintainer), so there is no independent blocking reviewer to gate
this. The step is documented as a **self-review checklist item the
author performs before merge**, with a documented future automation path
— extending the periodic cross-plugin-source consistency check (decision
#37, for `claude-code-plugins`) to this repo's own normative docs once
that check exists, so the control stops depending solely on author
diligence.

`conventions/README.md` gets a new "Changing a normative file" pointer
to this requirement; `distribution/README.md` gets a pointer alongside
its existing `THREAT-MODEL.md` reference.

### #27 tooling-gov-conventions-graduate-to-enforced

Decision: **graduate mechanically-checkable rules into
sync-manifest-tracked components.**

Reviewed every file under `conventions/` against
`enforceability-tiers.md`'s
deterministic/detect-then-judge/reasoning-only split. Finding: **no
ungraduated deterministic rule exists to graduate.** Every deterministic
(mechanically-checkable) rule already points to its owning component
instead of restating it:

| Convention area | Deterministic rule | Owning component | Tracked in
`sync-manifest.yml`? |
|---|---|---|---|
| Secrets (`review/security.md`) | no secrets in source | `gitleaks` |
yes |
| Comments (`review/code-quality.md`) | debt markers / tracker
provenance | `comment-hygiene` | yes (`comment-hygiene-action`) |
| Citations (`documentation-and-citations.md`) | cited URL resolves |
link check | yes (`lychee`) |
| TypeScript/JS (`review/overlays/typescript.md`) | lint/format/import
order, type correctness | `biome`, `tsconfig` | **no** — deliberately
native-package (`extends`) adoption per `distribution/README.md`'s
ownership model, not exact materialization |
| Python (`review/overlays/python.md`) | lint/format, type correctness |
`ruff`, `pyright` | yes |
| .NET (`review/overlays/dotnet.md`) | analyzers, code style, banned
symbols | `dotnet-analysis` | yes |
| Container build (`container-supply-chain.md`) | Docker Build checks,
OSV scans | *(none yet)* | **no** — the convention itself explicitly
defers this pending live-consumer admission evidence per
`docs/component-lifecycle.md`; graduating it without that evidence would
violate the same lifecycle contract |
| PR titles (`review/code-quality.md`) | Conventional Commits format |
*(ci-workflows `pr-title.yml`)* | out of this repo's materialization
surface — owned by `ci-workflows`, per README.md's ownership boundaries
|
| Naming (`naming.md`), label/issue-tracker usage
(`process/issue-tracker.md`), duplication
(`reference-dont-duplicate.md`) | — | — | self-declared reasoning-only;
no deterministic subset exists to graduate |

No `sync-manifest.yml` change is included. The one adjacent orphan
noticed in passing — `components/lefthook-typescript` exists, is fully
built, but is not registered in `sync-manifest.yml` for any target — is
tooling infrastructure, not a `conventions/` rule, and assigning it to a
target's `managed:` list is a separate adoption decision requiring its
own admission evidence; flagging it here for a follow-up rather than
folding it into this PR.

## Test plan

- [x] `npx markdownlint-cli2` — 0 errors across the full repo (71 files,
including the new/changed docs)
- [x] `lychee` — 21/21 links OK on the changed files (0 errors)
- [x] `typos` — clean on the changed files
- [x] `lefthook` pre-commit (typos, editorconfig, gitleaks,
markdownlint) — all passed at commit time
- [ ] Maintainer confirms the #27 classification table before merge — no
code/config changed, so this PR is prose-only and carries no behavioral
risk

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

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 15, 2026
… style (#124)

## Summary

Codifies six open decisions from the org's issue/PR consistency
assessment into `conventions/process/issue-tracker.md`:

- **#9** `entities-governance-doc-topology-reference-style` — abstracts
the personal-vs-org repo-topology prose (no more named
`melodic-software/github-iac` / `kyle-sexton/github-iac` links); points
at `github-iac`'s `GovernedRepositories.cs` as the sole source of truth
for which repositories are governed and how.
- **#23** `entities-closing-keyword-house-style-convention` — codifies
native GitHub closing keywords (`Closes`/`Fixes`/`Resolves` `#N`) as the
default house style, with `provisioning`'s stricter requirement (native
keyword plus a manual `## Related` section, per decisions #58/#59) as
the one named exception.
- **#25** `naming-issue-title-vocabulary-governance` — codifies issue
titles as free text with no enforced prefix vocabulary (no `[CC]`-style
conventional-commit tags), documenting the existing silence as a
deliberate choice.
- **#45** `entities-assignee-claiming-guidance-relevance` — keeps the
existing assignee-plus-lease claiming guidance but marks it explicitly
deferred, with an activation trigger (required reviewers /
multi-maintainer assignment contention).
- **#48** `metadata-codeowners-adoption` — adds a one-line note that
CODEOWNERS adoption is deferred, contingent on decision #11
(`required_approving_review_count` staying at 0 org-wide) — CODEOWNERS
is inert without required reviews.
- **#49** `comments-codify-human-conventions` — codifies three optional
documented conventions: a 🤖 footer marking bot-authored comments, citing
evidence when closing on it, and a 🔒 marker for claimed issues
(explicitly framed as the lightweight interim signal until #45's
mechanism activates).

Decisions Log:
https://claude.ai/code/artifact/232ecdce-8316-4880-8c0a-dc3c7dcf3a63

## Test plan

- [x] `lefthook run pre-commit` — typos, editorconfig, gitleaks,
markdownlint all pass
- [x] Grepped the file for residual `kyle-sexton`/named `github-iac`
repo references — none remain
- [ ] Human review of tone/placement against the rest of the process
conventions

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

---------

Co-authored-by: Claude Sonnet 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