From 0afa1ccdc1b143861fca9aeac84e8f328a4acc8e Mon Sep 17 00:00:00 2001 From: Mark Beacom Date: Sat, 10 Oct 2026 20:07:21 -0400 Subject: [PATCH 1/2] docs(adr): record ADR-0054's rung-2 dogfood and ADR-0055's implementation evidence - ADR-0054 item 8 ticked: https://adrkit.dev/decisions/ serves this repository's portal from site.yml via `uses: ./packages/ci/portal` (#310), verified by curl (version "1", 59 records, a real commit). Evidence rung is now 2 (maintainer-owned dogfood); rung 3 not claimed. - ADR-0055 items 1-7 and 9 ticked against #314 and the CI container smoke on main; item 8 (APIM measurement) stays open. Evidence rung 1. - ADR-0053 item 9 stays open: the publication record decides it. docs/sdk-surface.md now names the REST server as the long-lived consumer that exercises every handle member, beside the build-time portal. - AGENTS.md rung notes updated, and the broken ADR-0055 link (`-th.md`) fixed in AGENTS.md, README.md, CHANGELOG.md, and nine packages/server/src header comments. Signed-off-by: Mark Beacom --- AGENTS.md | 18 ++++-- CHANGELOG.md | 2 +- README.md | 2 +- ...ub-pages-built-outside-the-cli-from-the.md | 25 +++++--- ...n-the-oci-image-and-reach-mcp-clients-t.md | 57 +++++++++++++------ docs/sdk-surface.md | 22 ++++--- packages/server/src/bin.ts | 2 +- packages/server/src/config.ts | 2 +- packages/server/src/corpus.ts | 2 +- packages/server/src/messages.ts | 2 +- packages/server/src/openapi.ts | 2 +- packages/server/src/routes.ts | 2 +- packages/server/src/server.ts | 2 +- packages/server/src/shapes.ts | 2 +- packages/server/src/validate.ts | 2 +- 15 files changed, 94 insertions(+), 50 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 94a06a4..7bce913 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1077,9 +1077,13 @@ alone; it is the SDK's first consumer under [ADR-0053](./docs/adr/0053-implement-adrkit-sdk-over-core-s-kernels-and-accept-an-in-repo-consumer-as-its-r.md). The nested build-only Action (`packages/ci/portal`, `dist/portal-action.js`) is described below. -**Rung 1**: unit, contract, purity, and mutation tests, a Node run of the -bundled generator, and a maintainer browser check on this repository's corpus. -Load-bearing: +**Rung 2**: unit, contract, purity, and mutation tests, a Node run of the +bundled generator, and a maintainer browser check on this repository's corpus +(rung 1); and, since #310, `site.yml` builds this repository's corpus with the +shipped portal Action and publishes it at , the +maintainer-owned dogfood ADR-0054 names as rung 2. It runs on this repository, +not an isolated reference repository, and no external party has run it, so +rung 3 is not claimed. Load-bearing: - **It lives outside the CLI.** ADR-0033 decision 11 keeps HTML out of `@adrkit/cli`; do not add an `adr site` or `--format html`. @@ -1196,11 +1200,13 @@ external/community validation has been recorded. ## The read-only REST server (`packages/server`) `@adrkit/server` (private) is the image's `server` selector, under -[ADR-0055](./docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) +[ADR-0055](./docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) (**accepted**). **It authenticates no one.** `node:http` over `@adrkit/sdk` and `@adrkit/portal`'s pure builder, and nothing else (`check-deps` admits -exactly those two). **Rung 1**: unit, contract, and side-effect-denial tests -plus a local Podman smoke; the APIM path is unmeasured. Load-bearing: +exactly those two). **Implemented, rung 1** (#314): unit, contract, and +side-effect-denial tests, a local Podman smoke, and a CI container smoke of the +`server` selector under `--read-only` with a `:ro` corpus mount; the APIM path +is unmeasured. Load-bearing: - **The route table is the server.** `src/routes.ts` is data; the dispatcher matches it and `/openapi.json` is generated from it. Every row is `GET`; diff --git a/CHANGELOG.md b/CHANGELOG.md index 26aa1ac..a07a40f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,7 +69,7 @@ Until `1.0.0`, minor releases may include breaking changes `/api/v1/corpora/{corpus}`: `records`, `records/{id}`, `graph?kinds=`, `queue?asOf=`, `issues`, and `governing?path=`, plus `/api/v1/corpora`, `/openapi.json`, `/healthz`, and the decision portal at `/` - ([ADR-0055](docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md)). + ([ADR-0055](docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md)). Every answer is `{ corpus, commit, data }`, with the commit read from the `.adrkit-corpus.json` file the populator writes next to the records; a corpus without one is not served. Configure it with `ADRKIT_SERVER_CORPORA` diff --git a/README.md b/README.md index 3c9aa00..973d356 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ corpus it serves, private repositories included. The `server` selector serves a read-only REST API and the decision portal over one or more corpora -([ADR-0055](docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md)). +([ADR-0055](docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md)). It answers `GET` and `HEAD` only, and every other method gets `405`. Every data response is `{ corpus, commit, data }`. It runs no `git`, spawns no process, and opens no outbound connection. It binds `127.0.0.1` unless `ADRKIT_SERVER_HOST` diff --git a/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md b/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md index 86f323d..1def0db 100644 --- a/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md +++ b/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md @@ -333,11 +333,16 @@ workflow deploys to GitHub Pages: ## Evidence rung -Nothing here exists yet. The surface enters **rung 1** of ADR-0014 at best -when action items 1 to 7 land: unit, contract, and purity tests, each -observed failing first (ADR-0016), and a byte-identity check on the copies. -A dogfood build of this repository's own corpus from `site.yml` (item 8) -would be rung 2. No external party has run it, so rung 3 is absent. +**Rung 2** of ADR-0014, as this record defines it. Rung 1 landed with action +items 1 to 7 ([#292](https://github.com/mbeacom/adrkit/pull/292) and +[#302](https://github.com/mbeacom/adrkit/pull/302)): unit, contract, and purity tests, each observed failing +first (ADR-0016), and a byte-identity check on the copies. Rung 2 is item 8: +since [#310](https://github.com/mbeacom/adrkit/pull/310) (2026-10-10), +`site.yml` builds this repository's own corpus with the shipped portal Action +and publishes it at . That is a +maintainer-owned run on this repository, not on an isolated reference +repository, and no external party has run the portal, so rung 3 is not +claimed. ## Action items @@ -358,6 +363,12 @@ would be rung 2. No external party has run it, so rung 3 is absent. nested bundle. 7. [x] Add a test that the portal's shipped strings contain no ratifying or review command and no readiness word. -8. [ ] Build this repository's corpus from `site.yml` and publish it under - adrkit.dev as the rung-2 dogfood. +8. [x] Build this repository's corpus from `site.yml` and publish it under + adrkit.dev as the rung-2 dogfood. **Done 2026-10-10 in + [#310](https://github.com/mbeacom/adrkit/pull/310): `site.yml` runs + `uses: ./packages/ci/portal`. Checked 2026-10-10: `/decisions/` and + `/decisions/page/app.mjs` answer 200 as `text/html` and `text/javascript`, + and `/decisions/portal-data.json` has `version: "1"`, 59 records (the count + `adr lint` checks), and commit e491a78 of `main`. Recorded in + [#294](https://github.com/mbeacom/adrkit/issues/294#issuecomment-6103512935).** 9. [x] Ratify or reject this record. diff --git a/docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md b/docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md index 1acf9b9..a66c410 100644 --- a/docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md +++ b/docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md @@ -352,30 +352,53 @@ non-Azure deployment needs it. ## Evidence rung -**None yet; rung 1 at best when built** under ADR-0014. Nothing in this record -is implemented, and it depends on ADR-0053's SDK. Rung 1 would be the unit, +**Rung 1** under ADR-0014, since +[#314](https://github.com/mbeacom/adrkit/pull/314) (2026-10-10). The unit, contract, method-guard, verb-guard, error-text, side-effect-denial, and -OpenAPI-agreement tests above, each observed failing first (ADR-0016), plus a -local container smoke. The APIM path (clause 15) is unmeasured, and a -reference-repository or external run does not exist. +OpenAPI-agreement tests in `packages/server/test/` were each observed failing +against a planted break first (ADR-0016), as #314 lists; the side-effect-denial +test runs under Bun on the source and under Node on the bundle. A local Podman +smoke ran the all-in-one image read-only with a `:ro` corpus, and the CI +container smoke ("Smoke test the read-only server through the all-in-one +image") runs the `server` selector under `--read-only` with a `:ro` mount and +passed on `main`. The APIM path (clause 15, action item 8) is unmeasured, and +no reference-repository or external run exists, so neither rung 2 nor rung 3 +is claimed. ## Action items -1. [ ] Create `packages/server` (private) on `node:http` over `@adrkit/sdk`, +1. [x] Create `packages/server` (private) on `node:http` over `@adrkit/sdk`, with the routes, envelope, sidecar read, and swap of clauses 1 to 7, and its `check-deps` entry (`@adrkit/sdk` and `@adrkit/portal` only) with a - negative case. -2. [ ] Add the method guard, the verb and transition guard, the error-text + negative case. **Done 2026-10-10 in [#314](https://github.com/mbeacom/adrkit/pull/314): `scripts/check-deps.ts` admits + exactly the two, and `scripts/check-deps.test.ts` rejects a third + workspace package and an HTTP framework.** +2. [x] Add the method guard, the verb and transition guard, the error-text sentinel test, and the side-effect-denial variant, each observed failing. -3. [ ] Serve `/openapi.json` and test it against the route table. -4. [ ] Serve ADR-0054's bundle and its data file from the loaded handle, with - the headers of clause 9. -5. [ ] Add the `server` selector and local target to the `Containerfile` and + **Done 2026-10-10 in [#314](https://github.com/mbeacom/adrkit/pull/314): `methods`, `writing-verbs`, `error-text`, and + `side-effect-denial` tests, observed failing against a planted POST route, + writing verb, `String(error)` in a 500, and `execSync` (under both + runtimes).** +3. [x] Serve `/openapi.json` and test it against the route table. **Done + 2026-10-10 in [#314](https://github.com/mbeacom/adrkit/pull/314): generated from `src/routes.ts`; `openapi.test.ts` was + observed failing on planted drift.** +4. [x] Serve ADR-0054's bundle and its data file from the loaded handle, with + the headers of clause 9. **Done 2026-10-10 in [#314](https://github.com/mbeacom/adrkit/pull/314): the data file is built + per request by `buildPortalData` from the loaded handle at the sidecar's + commit, served with the clause 9 CSP (`frame-ancestors 'none'` observed + failing when dropped), `nosniff`, `no-referrer`, and no CORS header.** +5. [x] Add the `server` selector and local target to the `Containerfile` and `scripts/container-entrypoint.sh`, and a CI smoke under - `--read-only` with `:ro` mounts. -6. [ ] Agree the `.adrkit-corpus.json` sidecar with ADR-0056. -7. [ ] Document the selector in the README, leading with "this server - authenticates no one". + `--read-only` with `:ro` mounts. **Done 2026-10-10 in [#314](https://github.com/mbeacom/adrkit/pull/314): the + `server` target and selector, and a CI step that builds the target and + smokes `adrkit:ci server` under `--read-only` with a `:ro` corpus mount, + green on `main` at a5b0646 and e491a78.** +6. [x] Agree the `.adrkit-corpus.json` sidecar with ADR-0056. **Done + 2026-10-10: clause 4 here and ADR-0056 decision 4 carry the same contract + sentence, identical after whitespace and emphasis are normalized.** +7. [x] Document the selector in the README, leading with "this server + authenticates no one". **Done 2026-10-10 in [#314](https://github.com/mbeacom/adrkit/pull/314): the README's "The + read-only REST server" section opens with that sentence.** 8. [ ] Measure APIM's "REST API as MCP server" over these routes with a 2025-era and a `2026-07-28` client (ADR-0056). -9. [ ] Ratify or reject this record. +9. [x] Ratify or reject this record. **Ratified by `@mbeacom` on 2026-10-10.** diff --git a/docs/sdk-surface.md b/docs/sdk-surface.md index f02e85d..b222eb5 100644 --- a/docs/sdk-surface.md +++ b/docs/sdk-surface.md @@ -352,15 +352,19 @@ Decisions this left open, and how they were settled: ADR-0054) calls `openDecisions` and five of the six handle members (`records`, `issues`, `queue`, `graph`, `governing`; not `get`), and takes its default `asOf` from `queue()`'s echo. `bun test` runs it in CI over fixture corpora, and the portal Action's bundle is tested the - same way. That consumer is build-time only: it opens a corpus once per build, so the handle's - long-lived use is not exercised (ADR-0053 decision 8), and whether it satisfies ADR-0053 - action item 9 is for the publication record to decide. The consumer the surface was designed - for, a Backstage backend, does not exist yet. ADR-0031's own trade-off — *"the risk is that the guess hardens before the - Backstage plugin tests it"* — is not mitigated by this work, only made concrete enough to - criticize. -- **Implemented, not exercised.** The eight-call `explain` assembly the surface claims to absorb - is now written and tested equal to `adr explain --json`; its fitness for a long-lived server - consumer is still argued, not observed. + same way. That consumer is build-time only: it opens a corpus once per build. A second, + long-lived consumer now exists: the REST server (`packages/server`, ADR-0055) holds one + handle per corpus, serves `records`, `get`, `queue`, `graph`, `issues`, and `governing` from + it, and opens a fresh handle when a corpus's synced commit changes (clause 5), with its + tests and a CI container smoke over the built image. Together they exercise every handle + member, at build time and in a running process; whether that satisfies ADR-0053 action + item 9 is for the publication record to decide. The consumer the surface was first designed + for, a Backstage backend, exists only as a spike (`mbeacom/adrkit-backstage`), which used the + published CLI JSON, because an unpublished SDK consumed from source loads a stale prebuilt + core. +- **Implemented and exercised in a server.** The eight-call `explain` assembly the surface + claims to absorb is written and tested equal to `adr explain --json`, and the REST server's + `governing` route runs it per request. - **No release, and none prepared.** ADR-0031 clause 7 specifies `versioning: 'independent'` *when* released; wiring that into `scripts/release-pack.ts` now would prepare an act clause 8 does not authorize, so it is deliberately absent — and asserted absent by test, so its absence diff --git a/packages/server/src/bin.ts b/packages/server/src/bin.ts index db9d825..e39d981 100644 --- a/packages/server/src/bin.ts +++ b/packages/server/src/bin.ts @@ -1,6 +1,6 @@ /** * `adrkit-server`: the entry point of the image's `server` selector - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clauses 12 to 14). * * **This server authenticates no one.** It binds `127.0.0.1` unless `ADRKIT_SERVER_HOST` diff --git a/packages/server/src/config.ts b/packages/server/src/config.ts index 7a11d5e..aa384a1 100644 --- a/packages/server/src/config.ts +++ b/packages/server/src/config.ts @@ -1,6 +1,6 @@ /** * The server's configuration - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clauses 6 and 14), read from the environment once at start. * * | Variable | Default | Meaning | diff --git a/packages/server/src/corpus.ts b/packages/server/src/corpus.ts index 390d772..652ea4e 100644 --- a/packages/server/src/corpus.ts +++ b/packages/server/src/corpus.ts @@ -1,6 +1,6 @@ /** * One configured corpus: its sidecar, its loaded handle, and the swap between handles - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clauses 4 and 5). * * **The sidecar contract, worded as in ADR-0055 clause 4 and ADR-0056 clause 4:** diff --git a/packages/server/src/messages.ts b/packages/server/src/messages.ts index 07315ea..d3602ec 100644 --- a/packages/server/src/messages.ts +++ b/packages/server/src/messages.ts @@ -1,6 +1,6 @@ /** * Every error the server answers with, as fixed text looked up by code - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clause 8). No stderr, exception message, stack, or file system path reaches a response: * an error body is built from this table and nothing else. */ diff --git a/packages/server/src/openapi.ts b/packages/server/src/openapi.ts index 68d764e..297b5eb 100644 --- a/packages/server/src/openapi.ts +++ b/packages/server/src/openapi.ts @@ -1,6 +1,6 @@ /** * `/openapi.json`, generated from the route table - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clause 11). Pure. Every operation is a `get`; there is no other method to describe. * * OpenAPI 3.0.3 rather than 3.1, because 3.0 is the version APIM's importer documents fully. diff --git a/packages/server/src/routes.ts b/packages/server/src/routes.ts index 10c03a5..e825af1 100644 --- a/packages/server/src/routes.ts +++ b/packages/server/src/routes.ts @@ -1,6 +1,6 @@ /** * The route table: every path this server answers, as data - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clauses 1, 2, 9, and 11). * * The dispatcher matches against this table and nothing else, and `/openapi.json` is generated diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index 52ec678..11ea695 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -1,6 +1,6 @@ /** * The read-only HTTP server - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md)). + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md)). * * `node:http` and nothing else (clause 10). The handler: * diff --git a/packages/server/src/shapes.ts b/packages/server/src/shapes.ts index 85c561f..5fc48e0 100644 --- a/packages/server/src/shapes.ts +++ b/packages/server/src/shapes.ts @@ -1,6 +1,6 @@ /** * The response shapes of `/api/v1`, projected field by field from the SDK's - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clauses 1, 3, and 7). * * Projected rather than passed through, for two reasons. The canonical serializer refuses diff --git a/packages/server/src/validate.ts b/packages/server/src/validate.ts index 7f10102..71d2dbb 100644 --- a/packages/server/src/validate.ts +++ b/packages/server/src/validate.ts @@ -1,6 +1,6 @@ /** * Validation of everything a request carries, before any SDK call - * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-th.md) + * ([ADR-0055](../../../docs/adr/0055-serve-a-read-only-rest-api-over-the-sdk-in-the-oci-image-and-reach-mcp-clients-t.md) * clauses 7 and 8). Pure: no clock (the caller passes `now`), file, or environment. */ From e59e7ac7c640d8e99be0e0b8cf8c86894da83f55 Mon Sep 17 00:00:00 2001 From: Mark Beacom Date: Sat, 10 Oct 2026 20:13:14 -0400 Subject: [PATCH 2/2] docs(adr): keep ADR-0054 at rung 1; the adrkit.dev deploy is dogfood, not rung 2 Copilot pointed out that ADR-0014 defines rung 2 as a run in a separate, isolated reference repository with reproducible, self-verifying evidence, and ADR-0053 records that an in-repository consumer stays rung 1. Item 8 stays ticked because it was done as written, but the evidence rung is 1, item 8's own 'rung-2' label is noted as an overstatement, and rung 2 is named as a portal Action run in an isolated reference repository such as adrkit-t018-dogfood. AGENTS.md matches. Signed-off-by: Mark Beacom --- AGENTS.md | 17 ++++++++------- ...ub-pages-built-outside-the-cli-from-the.md | 21 ++++++++++++------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7bce913..036cd73 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1077,13 +1077,13 @@ alone; it is the SDK's first consumer under [ADR-0053](./docs/adr/0053-implement-adrkit-sdk-over-core-s-kernels-and-accept-an-in-repo-consumer-as-its-r.md). The nested build-only Action (`packages/ci/portal`, `dist/portal-action.js`) is described below. -**Rung 2**: unit, contract, purity, and mutation tests, a Node run of the -bundled generator, and a maintainer browser check on this repository's corpus -(rung 1); and, since #310, `site.yml` builds this repository's corpus with the -shipped portal Action and publishes it at , the -maintainer-owned dogfood ADR-0054 names as rung 2. It runs on this repository, -not an isolated reference repository, and no external party has run it, so -rung 3 is not claimed. Load-bearing: +**Rung 1**: unit, contract, purity, and mutation tests, a Node run of the +bundled generator, and a maintainer browser check on this repository's corpus. +Since #310, `site.yml` also builds this repository's corpus with the shipped +portal Action and publishes it at . That is +supplemental dogfood, not rung 2: ADR-0014's rung 2 needs a run in a separate, +isolated reference repository, and an in-repository consumer stays at rung 1 +(ADR-0053). Load-bearing: - **It lives outside the CLI.** ADR-0033 decision 11 keeps HTML out of `@adrkit/cli`; do not add an `adr site` or `--format html`. @@ -1132,7 +1132,8 @@ documented workflow is in `site/src/content/docs/ci.mdx`. **Rung 1**: unit, contract, and mutation tests, and a Node run of the committed bundle against a git fixture. `site.yml` builds this repository's corpus with it into `/decisions/` on adrkit.dev and checks the bundle (`scripts/check-portal-bundle.ts`); -that is rung 2 only once a deploy has been observed serving it. Load-bearing: +that deploy is supplemental dogfood; rung 2 needs a run in an isolated reference +repository (ADR-0014). Load-bearing: - **Logic is `src/portal-action.ts`, wiring is the entrypoint.** Only `portal-action-entrypoint.ts` imports `@actions/*`, as for the queue Action, diff --git a/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md b/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md index 1def0db..4844380 100644 --- a/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md +++ b/docs/adr/0054-publish-a-static-decision-portal-for-github-pages-built-outside-the-cli-from-the.md @@ -333,16 +333,21 @@ workflow deploys to GitHub Pages: ## Evidence rung -**Rung 2** of ADR-0014, as this record defines it. Rung 1 landed with action -items 1 to 7 ([#292](https://github.com/mbeacom/adrkit/pull/292) and +**Rung 1** of ADR-0014. Rung 1 landed with action items 1 to 7 +([#292](https://github.com/mbeacom/adrkit/pull/292) and [#302](https://github.com/mbeacom/adrkit/pull/302)): unit, contract, and purity tests, each observed failing -first (ADR-0016), and a byte-identity check on the copies. Rung 2 is item 8: -since [#310](https://github.com/mbeacom/adrkit/pull/310) (2026-10-10), +first (ADR-0016), and a byte-identity check on the copies. Item 8 is done as +written: since [#310](https://github.com/mbeacom/adrkit/pull/310) (2026-10-10), `site.yml` builds this repository's own corpus with the shipped portal Action -and publishes it at . That is a -maintainer-owned run on this repository, not on an isolated reference -repository, and no external party has run the portal, so rung 3 is not -claimed. +and publishes it at . That is supplemental, +maintainer-owned dogfood evidence, **not rung 2**: ADR-0014 defines rung 2 as a +run in a separate, isolated reference repository with reproducible, +self-verifying, fail-closed evidence, and ADR-0053 records that an +in-repository consumer stays at rung 1. Item 8's own wording ("the rung-2 +dogfood") predates that reading and overstates it. Rung 2 needs the portal +Action run in an isolated reference repository such as +[`adrkit-t018-dogfood`](https://github.com/mbeacom/adrkit-t018-dogfood); rung 3 +(an external party) is not claimed. ## Action items