Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/credential-surface.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"name": "NPM_TOKEN",
"tokenClass": "npm Automation token, or a granular access token with publish rights on the @cosyte scope. A classic Publish token demands a 2FA one-time password CI cannot supply and dies with EOTP at the last step, after a green build.",
"storage": "organization",
"storageNote": "An organization secret on the cosyte org, shared by every @cosyte/* repository. A repository-level NPM_TOKEN silently OVERRIDES the organization one, so it must live in exactly one place; rotating it affects every @cosyte/* repository, not just this one.",
"storageNote": "An organization secret on the Cosyte org, shared by every @cosyte/* repository. A repository-level NPM_TOKEN silently OVERRIDES the organization one, so it must live in exactly one place; rotating it affects every @cosyte/* repository, not just this one.",
"requiredForPublish": true,
"registryAuth": true,
"exposures": [
Expand Down Expand Up @@ -48,7 +48,7 @@
}
],
"issuedForms": [{ "id": "npm-automation-token", "pattern": "npm_[A-Za-z0-9]{36}" }],
"retiredWhen": "An npm Trusted Publisher is registered for all eight @cosyte/* packages against org cosyte, repository config, workflow release.yml, environment release. Removing this token before that publisher exists breaks every publish, so the order is not negotiable. RELEASING.md, 'Still deferred: OIDC trusted publishing', has the sequence."
"retiredWhen": "An npm Trusted Publisher is registered for all eight @cosyte/* packages against org Cosyte, repository config, workflow release.yml, environment release. Removing this token before that publisher exists breaks every publish, so the order is not negotiable. RELEASING.md, 'Still deferred: OIDC trusted publishing', has the sequence."
},
{
"name": "RELEASE_PR_TOKEN",
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/no-emdash.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Em-dash gate

# The brand rule (founder directive 2026-07-24, written down in the knowledgebase repo
# at 06-brand/voice-and-tone.md: "No em dashes. Ever.") bans U+2014 outright across
# every cosyte surface, and names COMMIT MESSAGES explicitly. This workflow is the CI
# every Cosyte surface, and names COMMIT MESSAGES explicitly. This workflow is the CI
# half of that rule for config: the tracked files, and the text that is not a file.
#
# config was NOT clean when this landed, and the measurement behind that is the whole
Expand Down Expand Up @@ -57,7 +57,7 @@ name: Em-dash gate
#
# Both of those land on `main`, and the brand rule names commit messages. The PR BODY
# lands under no merge method GitHub offers, and is scanned anyway as deliberate
# over-strictness: it is a cosyte surface in its own right and it costs nothing to
# over-strictness: it is a Cosyte surface in its own right and it costs nothing to
# cover. All three are checked below. This is not hypothetical bookkeeping: a squash
# merge composes its message from the PR title and body, so a sweep whose own PR text
# carries an em dash reds this gate on its own merge.
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ no package, so entries here are **dated** rather than versioned.
`test/drift-check-phi-probe.test.ts` is where the controls actually run.

- **`@cosyte/script-utils`**, a new zero-dependency, zero-build package, so that the entry-point
guard every cosyte gate script needs lands **once** rather than being respelled per repo
guard every Cosyte gate script needs lands **once** rather than being respelled per repo
(`ENTRYPOINT-STRING-COMPARE`). It ships `isCliEntrypoint(import.meta.url)`. `website` (3 CLIs) and
`docs` (4 `.mjs` gates, one of them the real `test:build` gate) hold the same shape and are the
intended next consumers.
Expand Down Expand Up @@ -893,7 +893,7 @@ no package, so entries here are **dated** rather than versioned.
path, exactly as it would be in `main`. A per-field exception to net 1's non-empty rule is a
bigger surface than the cases it would buy.
- **THE HONEST BOUND: this closed a LATENT hole and nothing in the org moves.** `typesVersions` is
the only one of the three any cosyte manifest uses (`ncpdp` and `@cosyte/test-utils`), and in
the only one of the three any Cosyte manifest uses (`ncpdp` and `@cosyte/test-utils`), and in
BOTH of them every `typesVersions` target is already declared through `exports`, so the derived
set is byte-for-byte what it was. `imports` and `browser` have no users here at all. The claim
is not that anything shipped broken.
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# cosyte-config

> One enforced toolchain for every cosyte package, published as eight small config packages.
> One enforced toolchain for every Cosyte package, published as eight small config packages.

[![CI](https://img.shields.io/github/actions/workflow/status/cosyte/config/ci.yml?branch=main&label=CI)](https://github.com/cosyte/config/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/cosyte/config/blob/main/LICENSE)
Expand All @@ -17,7 +17,7 @@ Shared build/lint/format configuration for the @cosyte/\* packages.

## Why this exists

Every cosyte package needs the same TypeScript options, the same lint rules, the same formatter
Every Cosyte package needs the same TypeScript options, the same lint rules, the same formatter
settings, the same build and test wiring. Copied into each repository, those files drift: a rule
relaxed in one place to unblock a release stays relaxed, and nobody finds out until two packages
disagree about what "strict" means.
Expand All @@ -28,12 +28,12 @@ declares them as devDependencies, and a change to the standard reaches every rep
bump and `pnpm install`.

The standard these packages encode is [`drift-manifest.json`](drift-manifest.json), which is the
cosyte estate's engineering baseline and says of itself that it inherits its authority from no other
Cosyte estate's engineering baseline and says of itself that it inherits its authority from no other
document. Every requirement in it carries its own provenance note. There is no prose twin.

## Status

`cosyte-config` is on the cosyte 0.1.x line: the public API is settled and bump types follow ordinary semver.
`cosyte-config` is on the Cosyte 0.1.x line: the public API is settled and bump types follow ordinary semver.

This root package is `private: true` and is never published; it is the workspace that builds the
eight `@cosyte/*` packages below, all of which are on that same line. Still moving: the
Expand Down Expand Up @@ -63,10 +63,10 @@ that adopts it:
| Package | What it is | How a package consumes it |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| [`@cosyte/tsconfig`](packages/tsconfig) | `base.json` (type-check options) plus `library.json` (adds declaration and sourcemap emit) | `"extends": "@cosyte/tsconfig/base.json"` |
| [`@cosyte/eslint-config`](packages/eslint-config) | ESLint 10 flat config: unified `typescript-eslint` (`recommendedTypeChecked`), JSDoc gates on public exports, cosyte rules | `import cosyte from "@cosyte/eslint-config"; export default cosyte(import.meta.dirname);` |
| [`@cosyte/prettier-config`](packages/prettier-config) | The cosyte Prettier settings | `"prettier": "@cosyte/prettier-config"` in `package.json` |
| [`@cosyte/tsup-config`](packages/tsup-config) | The cosyte tsup baseline: dual ESM and CJS with declarations, ES2023, treeshake on | `import { cosyteTsup } from "@cosyte/tsup-config";` |
| [`@cosyte/vitest-config`](packages/vitest-config) | The cosyte Vitest baseline: v8 coverage with gating per-directory thresholds, plus the runnable-docs snippet suite | `import { cosyteVitest } from "@cosyte/vitest-config";` |
| [`@cosyte/eslint-config`](packages/eslint-config) | ESLint 10 flat config: unified `typescript-eslint` (`recommendedTypeChecked`), JSDoc gates on public exports, Cosyte rules | `import cosyte from "@cosyte/eslint-config"; export default cosyte(import.meta.dirname);` |
| [`@cosyte/prettier-config`](packages/prettier-config) | The Cosyte Prettier settings | `"prettier": "@cosyte/prettier-config"` in `package.json` |
| [`@cosyte/tsup-config`](packages/tsup-config) | The Cosyte tsup baseline: dual ESM and CJS with declarations, ES2023, treeshake on | `import { cosyteTsup } from "@cosyte/tsup-config";` |
| [`@cosyte/vitest-config`](packages/vitest-config) | The Cosyte Vitest baseline: v8 coverage with gating per-directory thresholds, plus the runnable-docs snippet suite | `import { cosyteVitest } from "@cosyte/vitest-config";` |
| [`@cosyte/script-utils`](packages/script-utils) | Zero-dependency helpers for the gate scripts in `scripts/`: `isCliEntrypoint` and the shared PHI-scan engine | `import { isCliEntrypoint } from "@cosyte/script-utils";` |
| [`@cosyte/test-utils`](packages/test-utils) | The shared conformance kit for the parsers: round-trip, lenient-mode, immutability, warning-code and PHI-leak runners | `import { roundTripProperty } from "@cosyte/test-utils";` |
| [`@cosyte/process`](packages/process) | One `cosyte-process` bin behind build, test, lint, typecheck, format and check, so script bodies stop being hand-maintained | `"build": "cosyte-process build"` |
Expand Down Expand Up @@ -143,7 +143,7 @@ grades `config` only; an estate-wide README group is a separate change.

## The estate baseline, and who it binds

[`drift-manifest.json`](drift-manifest.json) IS the cosyte engineering baseline: it declares what
[`drift-manifest.json`](drift-manifest.json) IS the Cosyte engineering baseline: it declares what
every repository in the estate owes, and `pnpm run drift` grades each one against it and prints a
per-repo worklist. `pnpm run drift:validate` validates the standard itself against
[`drift-manifest.schema.json`](drift-manifest.schema.json) with nothing installed.
Expand Down
2 changes: 1 addition & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ published.
build even runs.
- **Revoke.** On npmjs.com, Access Tokens, revoke the old token **after** the new one is installed and
verified, not before: the two steps overlap deliberately so no release window is left with no
working token. Then re-read `gh secret list --org cosyte` and confirm one entry, one value.
working token. Then re-read `gh secret list --org Cosyte` and confirm one entry, one value.
- **Compensating action.** If the token is believed compromised, invert the order: **revoke first**,
accept that every `@cosyte/*` publish is blocked until a replacement is installed, and say so in the
org channel because thirteen other repositories share it. Then `npm token list` and audit recent
Expand Down
2 changes: 1 addition & 1 deletion documentation/decisions/0002-the-0-1-0-version-line.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- **Supersedes:** the sentence "the package stays on the **`0.0.x`-until-first-alpha** ladder",
which stood in all eight package changelogs, in the root `CHANGELOG.md`, in `README.md` and in
`.changeset/README.md` at commit `b78e2d977ac7615513c21f582c5efe5e42734209`; and the house
skeleton's `## Status` sentence "is on the cosyte 0.0.x ladder: the public API is not yet settled
skeleton's `## Status` sentence "is on the Cosyte 0.0.x ladder: the public API is not yet settled
and may change in any release", which stood in all nine governed READMEs. `scripts/readme-check.mjs`
compels the settled-line sentence in its place, resolving each package's line from its manifest
version and the pending changesets.
Expand Down
2 changes: 1 addition & 1 deletion documentation/drift-enforcement.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Drift enforcement: which repos the baseline's verdict binds

`drift-manifest.json` is the cosyte estate's engineering baseline, and
`drift-manifest.json` is the Cosyte estate's engineering baseline, and
`scripts/drift-check.js` grades every repo against it. This file answers the one question the
baseline used to leave to silence: **whose failure is anybody's problem?**

Expand Down
2 changes: 1 addition & 1 deletion drift-manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "./drift-manifest.schema.json",
"manifestVersion": 2,
"standing": "THIS FILE IS THE STANDARD. It is the cosyte estate's engineering baseline and it inherits its authority from no other document: there is no prose twin, and by operator decision none is to be written. Every requirement below carries its own provenance note saying where it was derived from, so no requirement is inherited unexamined. scripts/drift-check.js evaluates it and prints a per-repo WORKLIST; scripts/validate-drift-manifest.mjs validates this file against drift-manifest.schema.json, which ships beside it and needs no install to run. THE AUTHOR IS A SUBJECT TOO: configSubject below states which of these requirements config itself is held to and which it is exempt from, so the repo that publishes the standard is graded by it rather than standing outside it. AND NO ADVISORY RANGE IS TRANSCRIBED HERE: an override cites advisory IDENTIFIERS, and the ranges are read from the advisory record at check time, because a transcribed range decays silently while the sentence beside it still reads true. Drift is EXPECTED while the migration runs: the report is the worklist, never a claim of health.",
"standing": "THIS FILE IS THE STANDARD. It is the Cosyte estate's engineering baseline and it inherits its authority from no other document: there is no prose twin, and by operator decision none is to be written. Every requirement below carries its own provenance note saying where it was derived from, so no requirement is inherited unexamined. scripts/drift-check.js evaluates it and prints a per-repo WORKLIST; scripts/validate-drift-manifest.mjs validates this file against drift-manifest.schema.json, which ships beside it and needs no install to run. THE AUTHOR IS A SUBJECT TOO: configSubject below states which of these requirements config itself is held to and which it is exempt from, so the repo that publishes the standard is graded by it rather than standing outside it. AND NO ADVISORY RANGE IS TRANSCRIBED HERE: an override cites advisory IDENTIFIERS, and the ranges are read from the advisory record at check time, because a transcribed range decays silently while the sentence beside it still reads true. Drift is EXPECTED while the migration runs: the report is the worklist, never a claim of health.",
"estate": {
"provenance": "The umbrella's .gitmodules is the list of record for repo names, PATHS and hazards. These are its 24 submodule PATHS as of 2026-08-29, read for S0226. Repos are addressed by PATH and never by submodule NAME: the org profile repo is NAMED `.github` and PATHED `github-profile`, and since the checker resolves a repo by joining the umbrella root with the name it is given, and the umbrella root has its own `.github/` directory, addressing that repo by name would silently grade the umbrella's own workflows.",
"addressedBy": "path",
Expand Down
4 changes: 2 additions & 2 deletions drift-manifest.schema.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://cosyte.com/schemas/drift-manifest.schema.json",
"title": "cosyte drift manifest",
"description": "The shape of drift-manifest.json, which IS the cosyte engineering baseline. Validated by scripts/validate-drift-manifest.mjs, which implements the subset of JSON Schema used here and nothing more: a manifest that needs a keyword the validator does not know is a change to BOTH files. The subset is type, required, properties, additionalProperties, patternProperties, propertyNames, items, minItems, minProperties, minLength, minimum, uniqueItems, enum, const, pattern and local $ref into $defs. No remote references: this file must validate with no network and no node_modules.",
"title": "Cosyte drift manifest",
"description": "The shape of drift-manifest.json, which IS the Cosyte engineering baseline. Validated by scripts/validate-drift-manifest.mjs, which implements the subset of JSON Schema used here and nothing more: a manifest that needs a keyword the validator does not know is a change to BOTH files. The subset is type, required, properties, additionalProperties, patternProperties, propertyNames, items, minItems, minProperties, minLength, minimum, uniqueItems, enum, const, pattern and local $ref into $defs. No remote references: this file must validate with no network and no node_modules.",
"type": "object",
"additionalProperties": false,
"required": [
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-config/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pre-alpha rule. See

### Changed

- Documentation and source comments no longer use em dashes, in line with the cosyte brand
- Documentation and source comments no longer use em dashes, in line with the Cosyte brand
voice. No rule, option, or behaviour change.

## [0.0.4] - 2026-06-26
Expand Down Expand Up @@ -72,7 +72,7 @@ pre-alpha rule. See

### Added

- Initial release of the ESLint 9 flat config: `recommendedTypeChecked` + the cosyte guardrails (no `any`,
- Initial release of the ESLint 9 flat config: `recommendedTypeChecked` + the Cosyte guardrails (no `any`,
no unjustified casts, JSDoc + `@example` gate on public exports, `no-console` in library code).

(`0.0.1` was never published.)
6 changes: 3 additions & 3 deletions packages/eslint-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# @cosyte/eslint-config

> The cosyte lint bar in one factory call: no `any`, no undocumented public export, no drift.
> The Cosyte lint bar in one factory call: no `any`, no undocumented public export, no drift.

[![npm version](https://img.shields.io/npm/v/@cosyte/eslint-config.svg)](https://www.npmjs.com/package/@cosyte/eslint-config)
[![CI](https://img.shields.io/github/actions/workflow/status/cosyte/config/ci.yml?branch=main&label=CI)](https://github.com/cosyte/config/actions/workflows/ci.yml)
Expand All @@ -24,12 +24,12 @@ keeps a published API from shipping undocumented. Copied per repository, those r
locally to unblock a release and stay relaxed.

The nearest alternative is `eslint-config-airbnb` or a hand-rolled flat config per repo. Neither
encodes the cosyte rules, and neither closes the drift: this is a published package, so a rule added
encodes the Cosyte rules, and neither closes the drift: this is a published package, so a rule added
here reaches every consumer as a version bump.

## Status

`@cosyte/eslint-config` is on the cosyte 0.1.x line: the public API is settled and bump types follow ordinary semver.
`@cosyte/eslint-config` is on the Cosyte 0.1.x line: the public API is settled and bump types follow ordinary semver.

The factory signature `cosyte(tsconfigRootDir, opts?)` is settling, but the RULE SET behind it is
not: rules are added as the parsers find gaps, and a version bump can therefore red a consumer that
Expand Down
2 changes: 1 addition & 1 deletion packages/prettier-config/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pre-alpha rule. See

### Changed

- Documentation no longer uses em dashes, in line with the cosyte brand voice. No setting
- Documentation no longer uses em dashes, in line with the Cosyte brand voice. No setting
change.

## [0.0.2] - 2026-06-25
Expand Down
Loading
Loading