Skip to content

feat(hygiene): add editorconfig base + checker module - #3

Merged
kyle-sexton merged 1 commit into
mainfrom
feat/base-hygiene
Jun 22, 2026
Merged

feat(hygiene): add editorconfig base + checker module#3
kyle-sexton merged 1 commit into
mainfrom
feat/base-hygiene

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

What

Adds the language-agnostic base hygiene layer: the copy-only root configs plus a referenceable editorconfig checker module, following the proven one-module vertical-slice pattern (config + fixtures + harness test + CI + README).

  • .editorconfig (root, new) — decoupled superset: universal defaults plus the languages present in this repo (Markdown, shell, PowerShell) and the generic Windows batch class. Language source overlays extend it when they land.
  • .gitattributes (root, refined) — the single authority for line endings. * text=auto eol=lf is the deterministic LF default; .cmd/.bat override to CRLF. .ps1/.psm1/.psd1 stay LF — verified empirically to run on both PowerShell 7 and Windows PowerShell 5.1 (the PowerShell repo pins LF; the community template pins CRLF — flagged in-file so it isn't "corrected").
  • modules/editorconfig/ — referenceable .editorconfig-checker.json (end-of-line check disabled, since .gitattributes owns EOL; indent-size and max-line-length disabled as formatter-owned hints) + editorconfig.test.sh on the shell harness + README.
  • fixtures/editorconfig/{good,bad} + editorconfig.yml CI (SHA-pinned action, engine pinned, permissions: contents: read): self-lints the whole repo and runs the fixtures.

Design: canonical-at-root

.editorconfig/.gitattributes/.gitignore are discovered only by directory walk, so they cannot be referenced from a module path — they live canonically at the repo root, those root files are the published standard, and the repo dogfoods them. Only the referenceable checker config lives in the module. The "thin base + overlays" split applies to referenceable configs (PSSA, ruff), not to copy-only roots. Reconciles README.md + docs/migration-plan.md off the stale modules/base/ grouping.

Validation (local)

  • harness/shell/run-tests.sh: 4/4 passed (incl. new editorconfig.test.sh).
  • editorconfig-checker whole-repo self-lint: clean (good fixture passes, bad fixture flagged, exit 0 over the repo).
  • markdownlint: 8 files, 0 errors. shellcheck -x: clean. actionlint: clean.
  • Confirmed the new .gitattributes causes no EOL renormalization of existing tracked files.

Notes for review

  • .gitignore left unchanged — deliberate. The existing root .gitignore (OS/editor noise + CC worktrees + node_modules/) already is a clean agnostic base; language build-dirs belong to overlays. No additions needed this slice.
  • Deferred, threads kept in the plan: .dockerignore and .npmrc placement move to the relevant overlay rather than the agnostic base.

🤖 Generated with Claude Code

Add the language-agnostic base hygiene layer. Copy-only configs that tools
discover only by walking the directory tree cannot be referenced, so they live
canonically at the repo root and the repo dogfoods them; the referenceable
checker config lives in a module.

- .editorconfig (root): decoupled superset covering universal defaults plus the
  languages present in this repo (Markdown, shell, PowerShell) and the generic
  Windows batch class. Language source overlays extend it when they land.
- .gitattributes (root): the single authority for line endings. `* text=auto
  eol=lf` is the deterministic LF default; .ps1/.psm1/.psd1 stay LF (verified to
  run on PowerShell 7 and Windows PowerShell 5.1), .cmd/.bat override to CRLF.
  editorconfig end_of_line is an editor hint only.
- modules/editorconfig/: referenceable .editorconfig-checker.json (end-of-line
  check disabled — .gitattributes owns EOL; indent-size and max-line-length
  disabled as formatter-owned hints), editorconfig.test.sh on the shell harness,
  and README. Version left blank so the config adopts on any 3.x engine.
- fixtures/editorconfig/{good,bad} + editorconfig.yml CI (SHA-pinned action,
  engine pinned, contents: read): self-lints the whole repo and runs the fixtures.
- Reconcile README + migration-plan from the stale `modules/base/` grouping to
  the canonical-at-root model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton merged commit 500c661 into main Jun 22, 2026
9 checks passed
@kyle-sexton
kyle-sexton deleted the feat/base-hygiene branch June 22, 2026 16:03
kyle-sexton pushed a commit that referenced this pull request Jul 23, 2026
…bot-policy (#240)

Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.3 to
3.1.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/fastify/fast-uri/releases">fast-uri's
releases</a>.</em></p>
<blockquote>
<h2>v3.1.4</h2>
<h2>⚠️ Security Release</h2>
<p>Fix for <a
href="https://github.com/fastify/fast-uri/security/advisories/GHSA-v2hh-gcrm-f6hx">https://github.com/fastify/fast-uri/security/advisories/GHSA-v2hh-gcrm-f6hx</a></p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4">https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/fastify/fast-uri/commit/6aeece669e4166b2446a89f17c07a3b15dfb7ed4"><code>6aeece6</code></a>
Bumped v3.1.4</li>
<li><a
href="https://github.com/fastify/fast-uri/commit/2d50fbabc80e4d0884fe0f6a98fe118ce6faa353"><code>2d50fba</code></a>
fix: reject literal backslash in URI authority</li>
<li>See full diff in <a
href="https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=fast-uri&package-manager=npm_and_yarn&previous-version=3.1.3&new-version=3.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/melodic-software/standards/network/alerts).

</details>

## Related

- Resolves [Dependabot alert
#3](https://github.com/melodic-software/standards/security/dependabot/3)
(fast-uri host confusion, GHSA-v2hh-gcrm-f6hx) in
`components/dependabot-policy`.

No linked issue.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
kyle-sexton added a commit that referenced this pull request Jul 29, 2026
The label naming grammar mandated `<axis>: <value>` with no reasoning
recorded. A rule with no
rationale gets re-litigated: a recent design session re-derived the
whole balance from scratch,
recommending a switch twice before the evidence was complete. This
records the standing reasoning
beside the rule so the next reader finds the answer where the question
is asked.

## What changed

One file, `conventions/process/issue-tracker.md`, in the "Naming
grammar" section:

- The separator bullet now says slash is **declined on evidence rather
than by inheritance** —
neither form is an industry default, so this is a chosen convention —
and links `github-iac`'s
  ADR 0009 for the measurement.
- A short paragraph names the quoting hazard the space costs, the
mitigation, and why reversing
  the separator is not worth its cost.

The rule itself is unchanged. This documents the convention; it does not
alter it.

## Acceptance criteria

Inferred from the issue's own "Acceptance" list, unchanged:

- [x] The separator bullet states *why* colon-space, not only *that* it
is colon-space — the
rationale is in the bullet itself, matching how the "Long-form values"
bullet beside it carries
  its own reasoning.
- [x] The `label:<axis>: <value>` quoting hazard is named where a reader
would hit it — stated
directly under the grammar it is a consequence of, in the grammar's own
placeholder notation
rather than by naming a live label member (paragraph 7 commits this file
to naming no members).
- [x] The rationale points at the ADR for the measurement rather than
restating it — no counts,
percentages, or repository tallies are reproduced; only the shape that
survives the numbers aging.
- [x] The false "the fleet already migrated, so precedent supports
colon-space" argument is not
reproduced anywhere — verified by grep over the repository, which
returns no such claim in any
  tracked file, before or after this change.

## Evidence

**Both empirical claims were verified rather than inherited from the
issue.**

The quoting hazard, live against this repository:

| Form | Result |
| --- | --- |
| `--search 'label:priority: low'` | `0` results, exit `0`, **no error**
|
| `--search 'label:"priority: low"'` | `7` results |
| `--label 'priority: low'` | `7` results |

The seam claim, in source: `adapters/github/list-items.sh` calls `gh
issue list --json …labels…`
with no `--search`, and `lib/frontier.sh` filters with `jq index()` —
exact-string, core-side. The
citation targets `CONTRACT.md#verbs-core-public-surface`, the section
that owns that behavior.

**Independent review corrected a false claim before this PR opened.**
The first draft said "this
fleet's own labels are split between the two." That is wrong, and the
error originates in the
issue body itself: ADR 0009's 28-repository survey measures **external**
open-source projects
(Kubernetes, Terraform, React, Vue…), not `melodic-software`'s
repositories, whose labels are
uniformly colon-space. The text now attributes the ecosystem split to
the projects it was actually
measured across. The true fleet state is deliberately *not* used as an
argument — current state is
evidence, never justification.

Review also narrowed a second over-claim. "Automated lanes do not
inherit the hazard" was too
broad: ADR 0009 preserves a residual exposure for skill-authored search
templates, and
`work-items` CHANGELOG `0.24.2` records a real silent-zero in
`e2e-probe.sh` (`#1256`) caused by
exactly this. The text now scopes the mitigation to the tracker seam and
states plainly that a
lane building its own query string is still exposed — which keeps ADR
0009's revisit trigger #3
(a real silent-zero incident in a lane) intact rather than pre-empting
it.

Two further review findings were applied: cite the seam's contract
instead of restating its
filtering behavior, and drop a dash-separator disqualification that
would have added a third
prohibition the rule does not carry — a change to the convention, not
documentation of it.

## Cross-doc reconciliation

`conventions/process/issue-tracker.md` is a normative doc, so
`distribution/governance-process.md`
requires the author to confirm no other doc is left contradicting the
change. Performed:

- Swept all 104 tracked markdown files for `naming grammar`,
`separator`, `colon`, `slash`,
`gh label`, `label:`, and `tracker seam`. No other file states a
label-separator rule;
`conventions/process/README.md` describes this file as owning the
grammar, which stays true.
- `conventions/engineering/naming.md` does not contradict the added
text.
- No duplication of the `gh label list` pagination note in paragraph 7,
or of the tracker-seam
mention later in the file — that cites `#lease-protocol` for lease
semantics, this cites
`#verbs-core-public-surface` for label filtering. Different facts,
different anchors.

**No other normative doc is left contradicting this change.**

## Verification

- `npm run lint:md` — 0 issues across 104 files
- `lefthook` pre-commit (typos, editorconfig, gitleaks, markdownlint) —
all green
- `lychee` — 0 errors on the authored tree; the ADR URL is a
private-repo link already excluded by
`lychee.toml` with a documented rationale, and the same repo is already
linked from
`conventions/process/autonomy-binding.md`. The link is marked "internal"
so a public reader can
tell an auth-walled target from a rotted one, and the rationale stands
on its own without it.

## Related

- Closes #268
- `melodic-software/github-iac` ADR 0009 — the measurement and the
balance this change points at
- `melodic-software/github-iac#176` — the work-class axis decision that
surfaced the missing rationale

---------

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