Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b5126b6
test(diagnostics): require no-fallback and hostile-input assurance
seonghobae Aug 12, 2026
6f550d3
test(diagnostics): require cross-engine browser assurance
seonghobae Aug 12, 2026
1cd03c5
test(diagnostics): include cross-engine and mobile browser projects
seonghobae Aug 12, 2026
23216d8
test(diagnostics): type browser assurance harness
seonghobae Aug 12, 2026
8817f8b
ci(diagnostics): add browser assurance TDD lane
seonghobae Aug 12, 2026
38103c8
test(diagnostics): add public browser diagnostics harness
seonghobae Aug 12, 2026
7dafa56
test(diagnostics): tolerate repeated redacted contract errors
seonghobae Aug 12, 2026
519cb58
fix(diagnostics): focus verified affected text
seonghobae Aug 12, 2026
b7e80b8
ci(release): carry canonical executable workflow
seonghobae Aug 12, 2026
382e9ee
ci(diagnostics): add one-shot review repair
seonghobae Aug 12, 2026
abfeb75
ci(diagnostics): externalize one-shot review patch
seonghobae Aug 12, 2026
e3e4bb5
ci(diagnostics): run one-shot review repair
seonghobae Aug 12, 2026
1a89ce0
ci(diagnostics): correct repeated verification repair anchor
seonghobae Aug 12, 2026
f82300e
ci(diagnostics): rerun corrected review repair
seonghobae Aug 12, 2026
c873d76
ci(diagnostics): correct hostile assertion repair
seonghobae Aug 12, 2026
69cf1fb
ci(diagnostics): rerun bounded review repair
seonghobae Aug 12, 2026
3308f0f
ci(diagnostics): validate one-shot script mutation
seonghobae Aug 12, 2026
267c9a7
ci(diagnostics): remove mutated one-shot scripts safely
seonghobae Aug 12, 2026
d5eab5c
test(release): reject vulnerable pnpm bootstrap
seonghobae Aug 12, 2026
48c59d0
ci(diagnostics): run release bootstrap regression
seonghobae Aug 12, 2026
0361697
fix(release): use repaired pnpm bootstrap
seonghobae Aug 12, 2026
413b3ac
test(security): assert diagnostic payload stays inert
seonghobae Aug 12, 2026
3974796
test(browser): declare harness React runtime deps
seonghobae Aug 12, 2026
ef6aaf5
test(browser): lock isolated React harness deps
seonghobae Aug 12, 2026
393c1a6
ci(diagnostics): remove obsolete self-modifying writer
seonghobae Aug 12, 2026
ca8bfe6
ci(diagnostics): remove obsolete review repair script
seonghobae Aug 12, 2026
49eca24
ci(diagnostics): remove obsolete repair counter
seonghobae Aug 12, 2026
52f6268
test(release): require artifact-specific SBOM provenance
seonghobae Aug 12, 2026
92f4cc4
test(release): execute artifact SBOM contract
seonghobae Aug 12, 2026
cd9440e
test(security): assert hostile explanation before invalidation
seonghobae Aug 12, 2026
6af99b9
test(release): read workflow from repository root
seonghobae Aug 12, 2026
4262224
fix(release): bind SBOMs to exact packages
seonghobae Aug 12, 2026
db73458
fix(ci): inherit pinned package bootstrap
seonghobae Aug 12, 2026
0688db9
test(diagnostics): cover unavailable editor focus
seonghobae Aug 12, 2026
9c0c3ec
test(browser): fail closed on missing diagnostics probe
seonghobae Aug 12, 2026
b69ed82
test(browser): key touch target checks to capability
seonghobae Aug 12, 2026
1ad319c
Merge live diagnostics package base
seonghobae Aug 12, 2026
00b6775
test(ci): require Playwright browser cache contract
seonghobae Aug 12, 2026
6e74a9b
ci(diagnostics): cache exact Playwright browser revisions
seonghobae Aug 12, 2026
bf3a065
fix(diagnostics): preserve focus across selection and dismissal
seonghobae Aug 13, 2026
ccad62d
test(ci): preserve diagnostics workflow hardening across stack
seonghobae Aug 13, 2026
ccd3946
chore(diagnostics): reconcile assurance with current stack
seonghobae Aug 13, 2026
c6c2799
test(ci): inherit current main pnpm bootstrap contract
seonghobae Aug 13, 2026
e4a121a
chore(ci): inherit current main release security contracts
seonghobae Aug 13, 2026
eb63517
test(docs): require canonical writing diagnostics guide
seonghobae Aug 13, 2026
d6cdb5c
docs(diagnostics): satisfy canonical guide contract
seonghobae Aug 19, 2026
b3aa916
docs(diagnostics): index canonical active guide
seonghobae Aug 19, 2026
56af8aa
ci(diagnostics): execute canonical documentation contract
seonghobae Aug 19, 2026
91dfddd
fix(docs): satisfy diagnostics guide vocabulary contract
seonghobae Aug 19, 2026
f9ab67c
test(release): require browser evidence setup headroom
seonghobae Aug 20, 2026
599d2eb
fix(release): give browser evidence finite setup headroom
seonghobae Aug 20, 2026
3e17ac7
Merge current writing-diagnostics package parent into assurance
seonghobae Aug 21, 2026
4bbef62
fix(release): preserve package SBOM contract across stack merge
seonghobae Aug 22, 2026
5835a27
test(ci): require diagnostics assurance exact-head checkout
seonghobae Aug 22, 2026
99157b3
fix(test): preserve safe pnpm action pin oracle
seonghobae Aug 22, 2026
3590261
fix(ci): run diagnostics assurance on exact PR head
seonghobae Aug 22, 2026
c9685a7
Merge current package Semgrep repair into assurance
seonghobae Aug 22, 2026
44d132f
Merge remote-tracking branch 'origin/feat/writing-diagnostics-package…
seonghobae Sep 4, 2026
4fbf302
Merge remote-tracking branch 'origin/feat/writing-diagnostics-package…
seonghobae Sep 4, 2026
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
93 changes: 57 additions & 36 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,48 +148,62 @@ jobs:
sh "$syft_installer" -v -b "$RUNNER_TEMP/syft-bin" v1.50.0
"$RUNNER_TEMP/syft-bin/syft" version
echo "$RUNNER_TEMP/syft-bin" >> "$GITHUB_PATH"
- name: Generate release SBOM
- name: Generate exact-package release SBOMs
run: |
set -euo pipefail
syft scan dir:. -o spdx-json > release/inkspan.spdx.json
- name: Validate release SBOM
mapfile -t npm_assets < <(
find release -maxdepth 1 -type f -name '*.tgz' -printf '%f\n' | LC_ALL=C sort
)
mapfile -t wheel_assets < <(
find release -maxdepth 1 -type f -name '*.whl' -printf '%f\n' | LC_ALL=C sort
)
if [[ ${#npm_assets[@]} -ne 1 || ${#wheel_assets[@]} -ne 1 ]]; then
echo "::error::SBOM generation requires exactly one npm tarball and one Office wheel."
exit 1
fi
syft scan "release/${npm_assets[0]}" -o spdx-json > release/editor-package.spdx.json
syft scan "release/${wheel_assets[0]}" -o spdx-json > release/office-package.spdx.json
- name: Validate exact-package release SBOMs
run: |
set -euo pipefail
node <<'NODE'
const { readFileSync, statSync } = require('node:fs');

const sbomPath = 'release/inkspan.spdx.json';
const sbom = JSON.parse(readFileSync(sbomPath, 'utf8'));
const packageMetadata = JSON.parse(readFileSync('package.json', 'utf8'));
const officeMetadata = readFileSync('office/pyproject.toml', 'utf8');
if (statSync(sbomPath).size > 16 * 1024 * 1024) {
throw new Error('Release SBOM exceeds the 16 MiB actions/attest input limit.');
}
if (sbom.spdxVersion !== 'SPDX-2.3') {
throw new Error(`Release SBOM must be SPDX-2.3; found ${sbom.spdxVersion ?? 'missing'}.`);
}
if (!Array.isArray(sbom.packages) || sbom.packages.length === 0) {
throw new Error('Release SBOM package inventory must not be empty.');
}
const sbomPackageNames = new Set(sbom.packages.map((pkg) => pkg.name));
if (packageMetadata.name !== '@contextualwisdomlab/cwl-editor') {
throw new Error('Release source has an unexpected editor package identity.');
}
if (!/^name\s*=\s*["']inkspan-office["']\s*$/m.test(officeMetadata)) {
throw new Error('Release source has an unexpected Office package identity.');
}
if (!sbomPackageNames.has(packageMetadata.name)) {
throw new Error('Release SBOM inventory must include the editor package identity.');
}
if (!sbomPackageNames.has('inkspan-office')) {
throw new Error('Release SBOM inventory must include the Office package identity.');

const expectedSboms = [
['release/editor-package.spdx.json', packageMetadata.name],
['release/office-package.spdx.json', 'inkspan-office'],
];
for (const [sbomPath, expectedPackageName] of expectedSboms) {
const sbom = JSON.parse(readFileSync(sbomPath, 'utf8'));
if (statSync(sbomPath).size > 16 * 1024 * 1024) {
throw new Error(`${sbomPath} exceeds the 16 MiB actions/attest input limit.`);
}
if (sbom.spdxVersion !== 'SPDX-2.3') {
throw new Error(`${sbomPath} must be SPDX-2.3; found ${sbom.spdxVersion ?? 'missing'}.`);
}
if (!Array.isArray(sbom.packages) || sbom.packages.length === 0) {
throw new Error(`${sbomPath} package inventory must not be empty.`);
}
const packageNames = new Set(sbom.packages.map((pkg) => pkg.name));
if (!packageNames.has(expectedPackageName)) {
throw new Error(`${sbomPath} must include exact package identity ${expectedPackageName}.`);
}
}
NODE
- name: Generate release checksums
run: |
set -euo pipefail
cd release
sha256sum -- *.tgz *.whl inkspan.spdx.json > SHA256SUMS
sha256sum -- *.tgz *.whl *.spdx.json > SHA256SUMS
- name: Transfer exact release artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand All @@ -204,7 +218,7 @@ jobs:
if: github.repository == 'ContextualWisdomLab/inkspan'
needs: build-release-artifacts
runs-on: ubuntu-24.04
timeout-minutes: 30
timeout-minutes: 60
permissions:
contents: read
env:
Expand Down Expand Up @@ -301,7 +315,7 @@ jobs:
- name: Verify bounded local release artifact set
run: |
set -euo pipefail
expected_asset_count=4
expected_asset_count=5
mapfile -t local_entries < <(
find release -mindepth 1 -maxdepth 1 -printf '%f\n' | LC_ALL=C sort
)
Expand All @@ -318,9 +332,10 @@ jobs:
|| ${#local_assets[@]} -ne $expected_asset_count \
|| ${#npm_assets[@]} -ne 1 \
|| ${#wheel_assets[@]} -ne 1 \
|| ! -f release/inkspan.spdx.json \
|| ! -f release/editor-package.spdx.json \
|| ! -f release/office-package.spdx.json \
|| ! -f release/SHA256SUMS ]]; then
echo "::error::Unexpected local release artifact set; require exactly one *.tgz, one *.whl, inkspan.spdx.json, and SHA256SUMS."
echo "::error::Unexpected local release artifact set; require exactly one *.tgz, one *.whl, editor-package.spdx.json, office-package.spdx.json, and SHA256SUMS."
exit 1
fi
- name: Attest release artifacts
Expand All @@ -329,21 +344,25 @@ jobs:
subject-path: |
release/*.tgz
release/*.whl
release/inkspan.spdx.json
release/editor-package.spdx.json
release/office-package.spdx.json
release/SHA256SUMS
- name: Attest release packages with SBOM
- name: Attest editor package with matching SBOM
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
with:
subject-path: |
release/*.tgz
release/*.whl
sbom-path: release/inkspan.spdx.json
subject-path: release/*.tgz
sbom-path: release/editor-package.spdx.json
- name: Attest Office package with matching SBOM
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
with:
subject-path: release/*.whl
sbom-path: release/office-package.spdx.json
- name: Verify generated attestations
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
for artifact in release/*.tgz release/*.whl release/inkspan.spdx.json release/SHA256SUMS; do
for artifact in release/*.tgz release/*.whl release/editor-package.spdx.json release/office-package.spdx.json release/SHA256SUMS; do
gh attestation verify "$artifact" --repo "$GITHUB_REPOSITORY"
done
for artifact in release/*.tgz release/*.whl; do
Expand Down Expand Up @@ -382,7 +401,7 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
expected_asset_count=4
expected_asset_count=5
mapfile -t local_entries < <(
find release -mindepth 1 -maxdepth 1 -printf '%f\n' | LC_ALL=C sort
)
Expand All @@ -399,9 +418,10 @@ jobs:
|| ${#local_assets[@]} -ne $expected_asset_count \
|| ${#npm_assets[@]} -ne 1 \
|| ${#wheel_assets[@]} -ne 1 \
|| ! -f release/inkspan.spdx.json \
|| ! -f release/editor-package.spdx.json \
|| ! -f release/office-package.spdx.json \
|| ! -f release/SHA256SUMS ]]; then
echo "::error::Unexpected local release artifact set; require exactly one *.tgz, one *.whl, inkspan.spdx.json, and SHA256SUMS."
echo "::error::Unexpected local release artifact set; require exactly one *.tgz, one *.whl, editor-package.spdx.json, office-package.spdx.json, and SHA256SUMS."
exit 1
fi

Expand Down Expand Up @@ -477,6 +497,7 @@ jobs:
gh release edit "$GITHUB_REF_NAME" \
--repo "$GITHUB_REPOSITORY" \
--draft=false

release_immutable="$(gh release view "$GITHUB_REF_NAME" \
--repo "$GITHUB_REPOSITORY" \
--json isImmutable \
Expand All @@ -492,7 +513,7 @@ jobs:
fi

gh release verify "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY"
for artifact in release/*.tgz release/*.whl release/inkspan.spdx.json release/SHA256SUMS; do
for artifact in release/*.tgz release/*.whl release/editor-package.spdx.json release/office-package.spdx.json release/SHA256SUMS; do
gh release verify-asset "$GITHUB_REF_NAME" "$artifact" \
--repo "$GITHUB_REPOSITORY"
done
Expand Down
90 changes: 90 additions & 0 deletions .github/workflows/writing-diagnostics-assurance-tdd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Writing Diagnostics Assurance TDD

on:
push:
branches:
- feat/writing-diagnostics-assurance
pull_request:
paths:
- 'src/components/**'
- 'src/writingDiagnosticsCanonicalDocumentation.test.ts'
- 'src/workflowExactHead.test.ts'
- 'src/releaseArtifactSbomContract.test.ts'
- 'tests/browser/**'
- 'docs/WRITING_DIAGNOSTICS.md'
- 'docs/README.md'
- '.github/workflows/release.yml'
- '.github/workflows/writing-diagnostics-assurance-tdd.yml'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: writing-diagnostics-assurance-tdd-${{ github.ref }}
cancel-in-progress: true

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
unit-assurance:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Run hostile-input, no-fallback, focus, documentation, release-provenance, and workflow assurance
run: >-
pnpm exec vitest run
src/components/writingDiagnosticsSecurity.test.tsx
src/components/writingDiagnosticsFocus.test.tsx
src/components/WritingDiagnosticsPanel.test.tsx
src/writingDiagnosticsCanonicalDocumentation.test.ts
src/releaseArtifactSbomContract.test.ts
src/workflowExactHead.test.ts
--pool=forks
--maxWorkers=1
- name: Typecheck assurance changes
run: pnpm typecheck

browser-assurance:
name: Writing diagnostics / Playwright 1.62.0
runs-on: ubuntu-24.04
timeout-minutes: 30
env:
PLAYWRIGHT_BROWSERS_PATH: /tmp/inkspan-playwright-browsers
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm --dir tests/browser install --frozen-lockfile
- name: Restore exact Playwright browser revisions
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: /tmp/inkspan-playwright-browsers
key: ${{ runner.os }}-playwright-${{ runner.arch }}-${{ hashFiles('tests/browser/pnpm-lock.yaml') }}
- name: Install Playwright revisions pinned by the browser-test lock
run: pnpm --dir tests/browser exec playwright install --with-deps chromium firefox webkit
- name: Run writing-diagnostic browser assurance on exact head
env:
INKSPAN_EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: >-
pnpm --dir tests/browser exec playwright test
specs/writing-diagnostics.browser.spec.ts
--config playwright.config.ts
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim
- Added the selected standalone Markdown or HTML value to an explicitly configured SSR native form field, preserving controlled-value precedence, external form association, React attribute escaping, and the synchronous post-hydration TipTap transaction mirror

### Security
- Added a fail-closed draft release asset inventory gate that requires exactly one npm tarball, one Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`, rejects stale or unexpected draft assets before immutable publication, and verifies every GitHub-reported `sha256:` asset digest against the transferred local file
- Added a fail-closed draft release asset inventory gate that requires exactly one npm tarball, one Office wheel, matching editor and Office package SBOMs, and `SHA256SUMS`, rejects stale or unexpected draft assets before immutable publication, and verifies every GitHub-reported `sha256:` asset digest against the transferred local file
- Kept SSR document disclosure opt-in through `formFieldName`; hidden-field values remain client-controlled submission data and do not replace host authentication, authorization, tenant isolation, CSRF defenses, server validation, durable concurrency, or persistence controls
- Kept collaborative Yjs document content out of server markup until the host-owned client collaboration lifecycle is bound
- Added packed headless Markdown authority verification that rejects external runtime imports, dynamic module loaders, ambient network/environment credential access, React/TipTap/Yjs runtime coupling, CWL host coupling, and model credential references from the dedicated conversion artifact
Expand Down
4 changes: 2 additions & 2 deletions docs/CONTRACTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Expected degraded states are explicit rather than mapped to false success:

A public release binds one exact integrated protected source head to package/artifact identity, applicable CI/security/accessibility/document-fidelity evidence, owned production coverage, public-docstring evidence, SBOM/provenance/reproducibility where configured, formal review requirements, rollback guidance, and post-publication smoke verification.

Before immutable publication, the canonical draft inventory is **exactly four regular top-level files**: exactly one npm tarball, exactly one Inkspan Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`. Missing, stale, unexpected, duplicate, non-regular, incompletely uploaded, or digest-mismatched assets fail closed. After upload and before publication, the authenticated paginated GitHub Releases API inventory must equal the local release directory by exact asset name, every remote asset must report an uploaded state, and every GitHub-reported `sha256:` digest must equal the digest of the exact transferred local file. The workflow does not silently delete an unexpected remote asset to make an ambiguous draft look clean.
Before immutable publication, the canonical draft inventory is **exactly five regular top-level files**: exactly one npm tarball, one Inkspan Office wheel, `editor-package.spdx.json`, `office-package.spdx.json`, and `SHA256SUMS`. Each package is scanned and attested only with its matching SBOM. Missing, stale, unexpected, duplicate, non-regular, incompletely uploaded, or digest-mismatched assets fail closed. After upload and before publication, the authenticated paginated GitHub Releases API inventory must equal the local release directory by exact asset name, every remote asset must report an uploaded state, and every GitHub-reported `sha256:` digest must equal the digest of the exact transferred local file. The workflow does not silently delete an unexpected remote asset to make an ambiguous draft look clean.

Rollback must preserve readable canonical documents and must not require silently reinterpreting persisted schema or selector-projection semantics. Host-owned migrations, persistence rollback, annotation re-anchoring, tenant recovery, and deployment rollback remain host responsibilities unless a future versioned contract explicitly assigns them to Inkspan.

Expand All @@ -155,7 +155,7 @@ Rollback must preserve readable canonical documents and must not require silentl
| editor chrome theming (Active PR / Proposed) | named `--cwl-*` tokens, DTCG interchange snapshot, Storybook inventory, inventoried pair contrast including `--cwl-accent` on `--cwl-accent-soft` | host brand CSS, contrast certification, Figma Variables, design-tool sync |
| naruon composition | stable local package/module boundary | authenticated compose transport, tenancy, provider/model policy |
| model assistance | deterministic proposal acceptance boundary | provider, prompt/data policy, credentials, human approval |
| release evidence | exact four-file draft inventory, package/artifact/digest verification and repository evidence | downstream deployment and operational rollout |
| release evidence | exact five-file draft inventory, package/artifact/digest verification and repository evidence | downstream deployment and operational rollout |

## Related canonical documents

Expand Down
2 changes: 1 addition & 1 deletion docs/OPERABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Release publication occurs only from an exact integrated protected head. The rel
Before publication:

1. fetch the current protected `main` ref and require the release tag event commit SHA to equal that exact integration tip, not merely be an ancestor of it;
2. build exactly four regular top-level release files: exactly one npm tarball, exactly one Inkspan Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`;
2. build exactly five regular top-level release files: exactly one npm tarball, exactly one Inkspan Office wheel, `editor-package.spdx.json`, `office-package.spdx.json`, and `SHA256SUMS`;
3. reject missing, duplicate, non-regular, stale, or unexpected local entries and verify the local digests;
4. after upload, query the authenticated paginated GitHub Releases API and require the resumed remote draft asset-name set to equal the local release directory exactly;
5. require every remote asset state to be uploaded and every GitHub-reported `sha256:` digest to equal the exact transferred local file digest;
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ This directory is the discoverable index for Inkspan's product, technical, secur
| [`TRD.md`](TRD.md) | Technical invariants, runtime boundaries, failure semantics and release evidence |
| [`CONTRACTS.md`](CONTRACTS.md) | Public package/API/event/schema/plugin/collaboration and host-integration contracts |
| [`package-distribution.md`](package-distribution.md) | Buyer-facing public npm package entrypoints, packaged contents, runtime dependency boundaries, and consumer verification |
| [`WRITING_DIAGNOSTICS.md`](WRITING_DIAGNOSTICS.md) | Active-PR host-owned semantic diagnostics boundary, deterministic revision integrity, privacy, accessibility and rollback contract |
| [`email-output.md`](email-output.md) | Deterministic email fragment/full-document authority, language/direction metadata, accessibility and host-owned transport boundary |
| [`print-output.md`](print-output.md) | Browser print/paged-media presentation, accessibility/fidelity limits, host-owned governed-export boundary, and rollback |
| [`design-tokens.md`](design-tokens.md) | Host-facing editor chrome tokens, DTCG 2025.10 interchange snapshot, and Storybook inventory (Active PR / Proposed) |
Expand Down
Loading
Loading