From a26f0dccb382b0277d8f8fb0298c04a14df74339 Mon Sep 17 00:00:00 2001 From: Qwynn Marcelle Date: Tue, 4 Aug 2026 11:14:34 -0400 Subject: [PATCH 1/2] docs: correct site repository name, visibility, protection, and conformance coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit META-246 (ledger items 21, 23) and META-267 (items 24, 25). Documentation truth only — no schema bytes, no stable read paths, no package metadata, no types. Site repository name (item 21) `workspacejson/site` does not exist and never did; the repository is `workspacejson/workspacejson.dev`. Corrected in 11 places across 8 files — README, OWNERSHIP, GOVERNANCE, SUPPORT, CONTRIBUTING, SECURITY, AGENTS and the Copilot instructions — not the three the audit listed. Both ASCII dependency diagrams recentred for the longer name. One occurrence is deliberately NOT changed: docs/adr/002-bounded-enrichment- program.md:47. ADR-002 is a governance record under an amendment protocol, and silently editing a record is exactly what that protocol exists to prevent. It is flagged for amendment instead. Repository visibility and protection (item 23) The README claimed the repository is private and on a plan without branch protection. It is public, and protection is enabled. But the replacement is not simply the inverse: measured against the GitHub API on 2026-08-04, required_approving_review_count : 0 enforce_admins : false rulesets : [] docs/repository-settings.md asserted "a pull request with at least one approving review" and "enforce on admins". Both are false. A pull request can merge with no human approval once CI is green, and the code-owner requirement cannot bind while the required count is 0 — GitHub requests code-owner review but does not block on it. That document then concluded the authority transfer "can proceed without creating a supply-chain window". That conclusion does not follow and is removed. The gap is currently harmless — this repository holds no npm credential and ships no release workflow — but it must be closed before authority transfers, not after. Schema $id bullet Also stale, in the opposite direction: `main` already carries the bare-host $id after META-272, while published @workspacejson/spec@0.4.4 still serves the `www.` host. Restated as the candidate-versus-released distinction rather than a live disagreement. Producer conformance coverage (items 24, 25) docs/conformance.md "Known gaps" claimed producer conformance is not mechanically checked here. It has been since PR #9. Corrected in place rather than dropped, and expanded to describe what the suite actually does: the invocation command, the five assertion groups, the external-candidate boundary so the producer does not grade itself, the mutation red tests including the baseline that stops it passing by rejecting everything, and — per the suite's own header — what it deliberately does not assert about per-file fileIndex values, which is ADR-003 amendment A-004's open question. The adjacent "no external conformance suite" bullet is narrowed rather than deleted: a producer suite exists, but it needs a caller-supplied candidate path, so an unaided implementer still cannot point at one published battery. Verification pnpm -r build && pnpm -r typecheck && pnpm -r test 221 passed (48 spec, 173 rules) check:docs 4 confirmed in the schema; 9 prose enumerations complete check:schema, check:examples, check:architecture, check:architecture:test PASS check:adr index matches records; no Accepted record on a placeholder check:conformance 28 passed, 0 failed, against the local workspacejson/cli candidate --- .github/copilot-instructions.md | 2 +- AGENTS.md | 2 +- CONTRIBUTING.md | 2 +- GOVERNANCE.md | 2 +- OWNERSHIP.md | 6 ++-- README.md | 23 +++++++++------ SECURITY.md | 2 +- SUPPORT.md | 2 +- docs/conformance.md | 50 ++++++++++++++++++++++++++++----- docs/repository-settings.md | 37 ++++++++++++++++-------- 10 files changed, 91 insertions(+), 37 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ef07cb7..b05bbe9 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -9,7 +9,7 @@ This repository is the canonical source of the workspace.json specification, JSO - Define contracts and deterministic reference behavior here. - Producer and generation orchestration belong in `workspacejson/cli`. - MCP, Codex, editor, and other host integrations belong in `workspacejson/integrations`. -- Site rendering and assembled documentation belong in `workspacejson/site`. +- Site rendering and assembled documentation belong in `workspacejson/workspacejson.dev`. - Never import `@marcelle-labs/*`, private Vreko source, or depend on `workspace.vreko.json`. - The standard is descriptive, never prescriptive. - The committed `.agents/workspace.json` must remain useful without a daemon. diff --git a/AGENTS.md b/AGENTS.md index 6994ff2..14d59fe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,7 @@ This repository owns contracts, not implementations. Before adding anything, che - **No producer code.** Generation lives in `workspacejson/cli`. - **No host integrations.** MCP, Codex and VS Code live in `workspacejson/integrations`. -- **No site rendering.** Documentation assembly lives in `workspacejson/site`. +- **No site rendering.** Documentation assembly lives in `workspacejson/workspacejson.dev`. - **No proprietary references.** `@marcelle-labs/*`, private Vreko source and `workspace.vreko.json` are prohibited. - **Descriptive, never prescriptive.** No enforcement, approval-gate or diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d644dd2..5d5494f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ and its deterministic reference behavior. It publishes `@workspacejson/spec` and - Read [`OWNERSHIP.md`](./OWNERSHIP.md) — it states what belongs here and what belongs in `workspacejson/cli`, `workspacejson/integrations` or - `workspacejson/site`. + `workspacejson/workspacejson.dev`. - Read [`GOVERNANCE.md`](./GOVERNANCE.md) — changes to the normative surface need an architecture decision record **merged before** implementation. Finding that out after writing the code is the expensive way. diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 40f77b0..73d369b 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -17,7 +17,7 @@ This repository decides: It does not decide how artifacts are produced, how hosts integrate, or how the website presents any of it. Those live in `workspacejson/cli`, -`workspacejson/integrations` and `workspacejson/site` respectively. +`workspacejson/integrations` and `workspacejson/workspacejson.dev` respectively. [`OWNERSHIP.md`](./OWNERSHIP.md) states the full boundary; it is enforced by `scripts/check-architecture.mjs` in CI rather than by convention. diff --git a/OWNERSHIP.md b/OWNERSHIP.md index 9fd7b6c..873a130 100644 --- a/OWNERSHIP.md +++ b/OWNERSHIP.md @@ -28,7 +28,7 @@ what a coordinated authority transfer must do. ## Consumes - no implementation-repository internals -- no `workspacejson/cli`, `workspacejson/integrations` or `workspacejson/site` code +- no `workspacejson/cli`, `workspacejson/integrations` or `workspacejson/workspacejson.dev` code - no `@marcelle-labs/*` package, no private Vreko source, no `workspace.vreko.json` `@workspacejson/rules` depends on `@workspacejson/spec` through the shared pnpm @@ -40,7 +40,7 @@ rewrites it to an exact version before publication. - producer or generation orchestration — that is `workspacejson/cli` - host integrations (MCP, Codex, VS Code) — that is `workspacejson/integrations` -- site rendering or documentation assembly — that is `workspacejson/site` +- site rendering or documentation assembly — that is `workspacejson/workspacejson.dev` - private Vreko behavior or any proprietary sidecar - **prescriptive policy** — enforcement rules, approval gates, merge blocking. The standard describes what a repository is; it does not dictate what a team @@ -55,7 +55,7 @@ workspacejson/standard <- depends on NONE of the others ↓ workspacejson/cli workspacejson/integrations \ / - workspacejson/site + workspacejson/workspacejson.dev ``` Proprietary repositories may consume released Apache-2.0 `@workspacejson/*` diff --git a/README.md b/README.md index 748a13b..143f04c 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ This is one of four, with one-way ownership: | **`workspacejson/standard`** *(this repo)* | specification, JSON Schema, standard types, validation semantics, deterministic rules, compatibility profiles, conformance fixtures, ADRs and governance | | `workspacejson/cli` | production and generation — the producer, repository scanning, deterministic reconciliation, CLI distribution | | `workspacejson/integrations` | host adapters — MCP, Codex, VS Code, skills and plugins | -| `workspacejson/site` | assembled, published documentation at `workspacejson.dev` | +| `workspacejson/workspacejson.dev` | assembled, published documentation at `workspacejson.dev` | Dependency direction is one-way: @@ -45,7 +45,7 @@ workspacejson/standard ↓ workspacejson/cli workspacejson/integrations \ / - workspacejson/site + workspacejson/workspacejson.dev ``` **This repository depends on none of the other three.** That is enforced @@ -231,17 +231,22 @@ Stated here rather than discovered later: - **This repository cannot publish.** Both packages are released from the historical repository, which holds the only credential. That is deliberate and enforced in CI. -- **The schema `$id` host disagrees with the canonical domain.** The schema - declares the `www.` host while the package manifests use the bare domain. Both - serve the schema, so nothing is broken, but the strings differ. Reconciling - them changes schema bytes and is tracked as a normative change. +- **The schema `$id` is reconciled on `main` but not in the released bytes.** + `main` declares the bare domain, matching the package manifests. The published + `@workspacejson/spec@0.4.4` still serves the `www.` host, because the fix + changes schema bytes and has not been released. Both hosts serve the schema, + so nothing is broken — but do not read `main` as released truth here. - **`v1.json` is a legacy filename**, not a claim that the format is at 1.0. - **Four ambient interop shims are retained** in `types/ambient.d.ts` for `simple-git`, `remark` and `ajv`. They are real CJS/ESM mismatches in third-party packages, tracked as their own work rather than papered over. -- **The repository is private and on a plan without branch protection.** Both - constraints and the gate they create before any publication authority are - recorded in [`docs/repository-settings.md`](./docs/repository-settings.md). +- **`main` requires passing CI but no approving review.** Branch protection is + enabled — required checks on Node 20/22 plus four-path producer conformance, + dismissed stale reviews, code-owner review, conversation resolution, and no + force-push or deletion — but `required_approving_review_count` is `0`. That is + a real gap against the gate this repository must satisfy before it holds + publication authority. Recorded in + [`docs/repository-settings.md`](./docs/repository-settings.md). ## License diff --git a/SECURITY.md b/SECURITY.md index ea205aa..54ae399 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -37,7 +37,7 @@ This repository owns the specification, schema, types, validation semantics and deterministic rules. Issues in repository generation belong to `workspacejson/cli`; issues in host adapters belong to `workspacejson/integrations`; issues in the published website belong to -`workspacejson/site`. +`workspacejson/workspacejson.dev`. ## Publication note diff --git a/SUPPORT.md b/SUPPORT.md index ffe4436..be77f5d 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -31,7 +31,7 @@ costs you a round trip: | `.agents/workspace.json` is not generated, or generated wrongly | `workspacejson/cli` | | A repository scan produced bad or missing data | `workspacejson/cli` | | MCP, Codex or VS Code integration misbehaves | `workspacejson/integrations` | -| Documentation on `workspacejson.dev` is wrong or stale | `workspacejson/site` | +| Documentation on `workspacejson.dev` is wrong or stale | `workspacejson/workspacejson.dev` | If a validation error is *reported by* a producer but the schema itself is wrong, it belongs here. When in doubt, file here and it will be redirected. diff --git a/docs/conformance.md b/docs/conformance.md index c5b9407..95ab498 100644 --- a/docs/conformance.md +++ b/docs/conformance.md @@ -201,19 +201,55 @@ contract. Stated plainly, because a conformance document that hides them is misleading: -- **There is no external conformance suite.** An independent implementation - cannot currently run a standard battery to claim conformance. What exists is - this repository's own examples and its reference validator. +- **There is no self-service conformance battery for an unaided implementer.** + A producer suite exists and is described below, but running it requires a + candidate path supplied by the caller. An independent implementation cannot + yet point at a single published battery and claim conformance without that + step. What ships otherwise is this repository's own examples and its + reference validator. - **`validateLegacy()` has no shipped example.** All four examples are v0.3 or v0.4, so the legacy path is covered by unit tests but not by an executable fixture a third party can point at. - **There are no negative examples.** The examples prove that valid documents validate. They do not prove that invalid documents are rejected — that is covered only by unit tests inside the package. -- **Producer conformance is not mechanically checked here.** The obligations - listed at the top of this document — `manual` preservation, material-change - write semantics — are stated in the contract and tested by producers, not - verified by a fixture in this repository. + +### Producer conformance IS mechanically checked here + +This bullet previously said the opposite. That was true when written and became +false when the executable contract landed; it is corrected rather than quietly +dropped. + +`scripts/check-producer-conformance.mjs` is the standard's assertion about what +any conforming producer must do. It measures an external candidate — the +producer does not grade itself: + +```bash +WORKSPACEJSON_CLI_CANDIDATE=/path/to/cli/packages/cli \ + pnpm run check:conformance + +pnpm run check:conformance:test # the mutation red tests +``` + +It asserts five groups: `generated.fileIndex` populated from repository +evidence, `generated.frameworkManifest` populated from repository evidence, +`manual.*` preserved verbatim and never fabricated, invalid artifacts failing +safely without destroying human evidence, and producer identity plus +determinism plus direct/mediated parity. It imports this repository's own +validator rather than re-implementing it, so there is no second source of truth +to drift. + +The mutation tests assert that each mutation actually changed bytes and that +the suite goes red *on the expected check* rather than on any failure, with a +baseline case asserting the unmutated candidate is accepted — so the suite +cannot pass by rejecting everything. + +**What it deliberately does not assert.** Nothing about per-file values inside +`generated.fileIndex`. `FileIndexEntry` declares every value field optional, so +`{}` is conformant. Those values are behavioral and git-derived, and whether +they may enter the stable contract is an open determination this repository +does not own — recorded as ADR-003 amendment A-004. Requiring them here would +pre-empt that ruling and fail a producer that is behaving correctly. Closing these gaps is real work with real design questions, and none of it is claimed as done. diff --git a/docs/repository-settings.md b/docs/repository-settings.md index fe35547..5339caa 100644 --- a/docs/repository-settings.md +++ b/docs/repository-settings.md @@ -58,7 +58,7 @@ now enabled: | Control | Status | Notes | | -- | -- | -- | -| Branch protection | **enabled** | PR + 1 approving review + CI on Node 20/22 + conversation resolution + codeowner review + block force-push/deletion. See below. | +| Branch protection | **enabled, with one gap** | PR + CI on Node 20/22 + conversation resolution + codeowner review + block force-push/deletion. **Required approving reviews is `0`, and admin enforcement is off.** See below. | | Secret scanning | **enabled** | Free for public repositories. | | Secret scanning push protection | **enabled** | Blocks commits containing detected secrets. | | Private vulnerability reporting | **enabled** | The advisory form at [`SECURITY.md`](../SECURITY.md) now resolves. | @@ -68,22 +68,35 @@ now enabled: ## Branch protection -Branch protection is **enabled** on `main` as of 2026-07-28. The protection -requires: +Branch protection is **enabled** on `main` as of 2026-07-28. Measured against the +GitHub API on 2026-08-04, it requires: -- a pull request with at least one approving review; -- required status checks: `test (20)`, `test (22)`, and `Four-path producer - conformance`; +- a pull request; +- required status checks, strict: `test (20)`, `test (22)`, and `Four-path + producer conformance`; - dismiss stale approvals on new commits; - require conversation resolution; - block force pushes and branch deletion; -- require review from code owners, so changes to the schema, the guards and the - release documents reach a maintainer — see [`.github/CODEOWNERS`](../.github/CODEOWNERS). -- enforce on admins. +- require review from code owners — see [`.github/CODEOWNERS`](../.github/CODEOWNERS). -This was a hard gate before publication authority. The protection is now in -place, so the authority transfer in `.github/RELEASE-AUTHORITY.md` can proceed -without creating a supply-chain window. +Two controls this document previously claimed are **not** in place: + +| Claimed | Measured | Consequence | +| -- | -- | -- | +| a pull request with at least one approving review | `required_approving_review_count: 0` | A pull request can merge with no human approval once CI is green. The code-owner requirement above cannot bind either — with a required count of `0`, GitHub requests code-owner review but does not block on it. | +| enforce on admins | `enforce_admins: false` | An administrator can bypass every control above. | + +No ruleset supplies these separately; `GET /repos/workspacejson/standard/rulesets` +returns `[]`. + +**This is a real gap against the publication-authority gate, not a formality.** +`.github/RELEASE-AUTHORITY.md` and the migration plan both treat protected, +reviewed release paths as a precondition for holding a credential. A repository +that can merge unreviewed and be bypassed by an admin does not meet that bar. The +gap is currently harmless here — this repository holds no npm credential and +ships no release workflow — but it must be closed *before* authority transfers, +not after. Setting `required_approving_review_count` to at least `1` is what makes +the existing code-owner requirement load-bearing. ## Repository metadata From dcdba7f77034f21744f2dfc07e2a8caeef4c7f7c Mon Sep 17 00:00:00 2001 From: Qwynn Marcelle Date: Tue, 4 Aug 2026 19:30:30 -0400 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20correct=20the=20branch-protection?= =?UTF-8?q?=20analysis=20=E2=80=94=20the=20defect=20is=20no=20independent?= =?UTF-8?q?=20reviewer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prior wording claimed `required_approving_review_count: 0` makes the code-owner requirement unable to bind. That is wrong, and it understated the problem in one place while overstating it in another. `require_code_owner_reviews` is an independent control: it blocks an affected pull request until a code owner approves, regardless of the general count. It is not inert. The actual defect is structural. Every path in .github/CODEOWNERS is owned solely by @qmarcelle, who authors the changes, and GitHub does not permit an author to approve their own pull request — so the code-owner gate cannot be satisfied from within. Administrator enforcement is off, so the same account can bypass it. The controls are configured; what is missing is a second person. Remediation restated accordingly: an independent code owner is the first requirement, not a higher approval count. Raising the count alone changes nothing while one account owns every path and authors every change. Also narrows "currently harmless". It is not a credentialed publication risk — no npm credential, no release workflow — but main here is the public canonical source of the standard, so unreviewed schema, guard and governance changes land the same way. --- README.md | 15 ++++++--- docs/repository-settings.md | 63 ++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 143f04c..2b55289 100644 --- a/README.md +++ b/README.md @@ -240,12 +240,17 @@ Stated here rather than discovered later: - **Four ambient interop shims are retained** in `types/ambient.d.ts` for `simple-git`, `remark` and `ajv`. They are real CJS/ESM mismatches in third-party packages, tracked as their own work rather than papered over. -- **`main` requires passing CI but no approving review.** Branch protection is +- **`main` has no enforceable independent-review path.** Branch protection is enabled — required checks on Node 20/22 plus four-path producer conformance, - dismissed stale reviews, code-owner review, conversation resolution, and no - force-push or deletion — but `required_approving_review_count` is `0`. That is - a real gap against the gate this repository must satisfy before it holds - publication authority. Recorded in + dismissed stale approvals, code-owner review, conversation resolution, and no + force-push or deletion. But the general `required_approving_review_count` is + `0`; code-owner review is enabled and does block affected pull requests, yet + every path in [`.github/CODEOWNERS`](./.github/CODEOWNERS) is owned solely by + `@qmarcelle`, who authors the changes — and an author cannot approve their own + pull request. Administrator enforcement is also off, so the administrator can + bypass the protection entirely. The controls exist; no combination of them + currently produces review by a second person. Recorded, with the remediation + it actually requires, in [`docs/repository-settings.md`](./docs/repository-settings.md). ## License diff --git a/docs/repository-settings.md b/docs/repository-settings.md index 5339caa..4088144 100644 --- a/docs/repository-settings.md +++ b/docs/repository-settings.md @@ -58,7 +58,7 @@ now enabled: | Control | Status | Notes | | -- | -- | -- | -| Branch protection | **enabled, with one gap** | PR + CI on Node 20/22 + conversation resolution + codeowner review + block force-push/deletion. **Required approving reviews is `0`, and admin enforcement is off.** See below. | +| Branch protection | **enabled; no independent-review path** | PR + CI on Node 20/22 + conversation resolution + codeowner review + block force-push/deletion. **General approving-review count is `0`, the sole code owner authors the changes, and admin enforcement is off.** See below. | | Secret scanning | **enabled** | Free for public repositories. | | Secret scanning push protection | **enabled** | Blocks commits containing detected secrets. | | Private vulnerability reporting | **enabled** | The advisory form at [`SECURITY.md`](../SECURITY.md) now resolves. | @@ -81,22 +81,61 @@ GitHub API on 2026-08-04, it requires: Two controls this document previously claimed are **not** in place: -| Claimed | Measured | Consequence | -| -- | -- | -- | -| a pull request with at least one approving review | `required_approving_review_count: 0` | A pull request can merge with no human approval once CI is green. The code-owner requirement above cannot bind either — with a required count of `0`, GitHub requests code-owner review but does not block on it. | -| enforce on admins | `enforce_admins: false` | An administrator can bypass every control above. | +| Claimed | Measured | +| -- | -- | +| a pull request with at least one approving review | `required_approving_review_count: 0` | +| enforce on admins | `enforce_admins: false` | No ruleset supplies these separately; `GET /repos/workspacejson/standard/rulesets` returns `[]`. -**This is a real gap against the publication-authority gate, not a formality.** +### The actual defect: no enforceable independent-review path + +These are four separate facts, and the defect is what they produce together — +not any one of them alone. + +1. **The general approving-review count is `0`.** No count-based approval is + required, so paths a code-owner rule does not reach are unprotected by review. +2. **Code-owner review is enabled and does bind.** `require_code_owner_reviews` + is an independent control: it blocks an affected pull request until a code + owner approves it, regardless of the general count. Nothing here should be + read as saying that control is inert — it is not. +3. **Every path has exactly one code owner, and that owner authors the changes.** + [`.github/CODEOWNERS`](../.github/CODEOWNERS) assigns `*` and every specific + path to `@qmarcelle`. GitHub does not permit a pull-request author to approve + their own pull request, so a self-authored change cannot satisfy the + code-owner requirement from within. +4. **Administrator enforcement is off.** `enforce_admins: false` means the + administrator — the same account — can bypass the protection entirely. + +The controls are configured. What is missing is a *second person*: no combination +of the above currently results in a change being reviewed by someone other than +its author. + +**This is not currently a credentialed package-publication risk**, because this +repository holds no npm credential and ships no release workflow. It is not +harmless in general — `main` here is the public canonical source of the standard, +and unreviewed changes to the schema, the guards, or the governance documents +land the same way. + +### Remediation + +Raising the approval count alone does not fix this. All four are required: + +1. **At least one independent maintainer or code owner** able to review + `@qmarcelle`-authored changes. Without this, nobody can satisfy point 3 above. +2. **At least one required approval** (`required_approving_review_count >= 1`), + so review is required on paths no code-owner rule reaches. +3. **Administrator enforcement**, or a no-bypass ruleset carrying a deliberately + bounded and documented release exception — bypass should be an explicit, + narrow act rather than the default posture. +4. **Continued protection of `.github/CODEOWNERS` itself**, so the ownership map + cannot be edited to route around the requirement. This is already in place at + `.github/CODEOWNERS:29` and must survive any change made for points 1–3. + `.github/RELEASE-AUTHORITY.md` and the migration plan both treat protected, -reviewed release paths as a precondition for holding a credential. A repository -that can merge unreviewed and be bypassed by an admin does not meet that bar. The -gap is currently harmless here — this repository holds no npm credential and -ships no release workflow — but it must be closed *before* authority transfers, -not after. Setting `required_approving_review_count` to at least `1` is what makes -the existing code-owner requirement load-bearing. +reviewed release paths as a precondition for holding a credential. This must be +closed *before* publication authority transfers, not after. ## Repository metadata