Skip to content

Commit 9099b1d

Browse files
committed
release: 1.5.0
The site ships in five more languages (Spanish, Brazilian Portuguese, Vietnamese, Japanese, Simplified Chinese) beside the English page of record, with a drift check on every build; Japanese and Chinese emphasis renders without Markdown's padding space; path order is byte order in the TypeScript SDK; the CLI reference says what the commands do; three clarifications on the frozen 1.0 specification line, no requirement changed; the site builds from any working directory; the version check gains a release mode that asserts the changelog date is stamped. Release pins refreshed under decision 0008; every package moves to 1.5.0. Signed-off-by: Vuong Nguyen <vuong@contexing.com>
1 parent 322f695 commit 9099b1d

590 files changed

Lines changed: 45732 additions & 1712 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
name: Translation correction
3+
about: A translated leji.org page says something the English page does not, or reads wrong
4+
title: '[locale] /route/: '
5+
---
6+
7+
**Page**: <!-- The URL of the translated page, e.g. https://leji.org/vi/quickstart/ -->
8+
9+
**What it says**
10+
11+
<!-- Quote the sentence as the page has it today. -->
12+
13+
**What it should say**
14+
15+
<!-- Your correction, in the same language. A whole sentence helps more than a word. -->
16+
17+
**Reference (optional)**
18+
19+
<!-- The English sentence it translates, or an established rendering of a term elsewhere. -->
20+
21+
<!-- Note: English is the page of record. Where a translation and the English page differ, the English text governs, so a correction brings the translation to the English meaning rather than the other way round. -->

.github/dependabot.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Dependabot configuration. fixtures/ holds the ecosystem-detection test fixtures,
2-
# several of which are deliberately malformed manifests; exclude-paths keeps every
3-
# Dependabot job (version updates and dependency-graph submission) from parsing them.
2+
# several of which are deliberately malformed manifests; exclude-paths keeps
3+
# Dependabot's update jobs from opening pull requests for them. The dependency
4+
# graph still parses every manifest it finds, fixtures included, so an alert on a
5+
# fixtures/ path is dismissed as "not used" rather than fixed there.
46
# open-pull-requests-limit: 0 leaves scheduled version-update PRs off; security
57
# updates and the dependency graph for the real manifests are unaffected.
68
version: 2

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ jobs:
305305
uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
306306
with:
307307
# The same goreleaser the release job installs (scripts/release-pins.env).
308-
version: "v2.18.0"
308+
version: "v2.18.1"
309309
workdir: packages/sdk-go
310310
args: check
311311

.github/workflows/release-checks.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ jobs:
116116
compare "packages/sdk-py/pyproject.toml" "$(grep -m1 '^version' packages/sdk-py/pyproject.toml | sed -E 's/.*"([^"]+)".*/\1/')"
117117
compare "packages/sdk-go SDKVersion" "$(sed -nE 's/^var SDKVersion = "([^"]+)".*/\1/p' packages/sdk-go/internal/schemas/schemas.go)"
118118
exit "$status"
119+
# And the release those manifests name carries its date: the CHANGELOG.md
120+
# heading for that version reads `## <version> · YYYY-MM-DD`, and the
121+
# CHANGELOG.json release entry, when the release carries one, names the same
122+
# day. A tag cut past an undated heading publishes one.
123+
- name: The release date is stamped
124+
run: node scripts/version.ts --check --release
119125

120126
python-dist:
121127
name: Python distribution (test, build, twine)
@@ -130,7 +136,7 @@ jobs:
130136
run: python -m pip install pip==26.2.1 && pip install -e ".[dev]" && pytest -q
131137
- name: Build sdist + wheel
132138
working-directory: packages/sdk-py
133-
run: python -m pip install build==1.5.0 && python -m build
139+
run: python -m pip install build==1.6.1 && python -m build
134140
# The gate the PyPI upload performs, on a distribution built the way the
135141
# upload builds one. Same function as the smoke and the pre-push hook, same
136142
# twine the publish action bundles.
@@ -177,7 +183,7 @@ jobs:
177183
uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
178184
with:
179185
# The same goreleaser the release job installs (scripts/release-pins.env).
180-
version: "v2.18.0"
186+
version: "v2.18.1"
181187
workdir: packages/sdk-go
182188
args: release --clean --skip=publish
183189
env:

.github/workflows/release-finalize.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ on:
1313
release_tag:
1414
description: "Tag the draft release is attached to (the goreleaser/Go tag)"
1515
required: true
16-
default: "packages/sdk-go/v1.4.1"
16+
default: "packages/sdk-go/v1.5.0"
1717

1818
permissions:
1919
contents: write # publish the release

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ jobs:
191191
run: python -m pip install pip==26.2.1 && pip install -e ".[dev]" && pytest -q
192192
- name: Build sdist + wheel
193193
working-directory: packages/sdk-py
194-
run: python -m pip install build==1.5.0 && python -m build
194+
run: python -m pip install build==1.6.1 && python -m build
195195
# The last gate before the irreversible act, on the exact bytes about to be
196196
# uploaded: the publish action rejects a distribution twine cannot render,
197197
# and it rejects it after the tag exists. Same function as the smoke and
@@ -247,7 +247,7 @@ jobs:
247247
with:
248248
# The action is pinned by SHA; this input pins the goreleaser it
249249
# installs, and mirrors GORELEASER_VERSION in scripts/release-pins.env.
250-
version: "v2.18.0"
250+
version: "v2.18.1"
251251
workdir: packages/sdk-go
252252
args: release --clean --skip=publish
253253
env:

CHANGELOG.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,44 @@
119119
],
120120
"proposedBy": "Vuong Nguyen",
121121
"approvedBy": "Vuong Nguyen"
122+
},
123+
{
124+
"id": "viewer-theme-link",
125+
"date": "2026-08-27",
126+
"type": "added",
127+
"summary": "viewer.theme.link: optional hex link color, applied only above 4.5:1 on the inline-code ground; otherwise a warning and the fixed tone.",
128+
"paths": [
129+
"schemas/",
130+
"packages/sdk/",
131+
"packages/sdk-py/",
132+
"packages/sdk-go/",
133+
"packages/mcp/",
134+
"packages/site/",
135+
"templates/",
136+
"fixtures/"
137+
],
138+
"proposedBy": "Vuong Nguyen",
139+
"approvedBy": "Vuong Nguyen"
140+
},
141+
{
142+
"id": "release-1-5-0",
143+
"date": "2026-09-14",
144+
"type": "changed",
145+
"summary": "Three clarifications on the frozen 1.0 specification line, no requirement changed: conformance.md states what the boot-profile item's machine check covers and what rides the opt-in content lint; context-layer.md requirement 4 and the manifest schema's rootPath description name the viewer's homepage, logo, and favicon as the one path convention written relative to the context root; governance.md reads \"the owner tends the system's health\". All packages move to 1.5.0 together.",
146+
"paths": [
147+
"spec/conformance.md",
148+
"spec/context-layer.md",
149+
"spec/governance.md",
150+
"schemas/context-manifest.schema.json",
151+
"packages/sdk/",
152+
"packages/sdk-py/",
153+
"packages/sdk-go/",
154+
"packages/mcp/",
155+
"packages/create-leji/",
156+
"packages/site/"
157+
],
158+
"proposedBy": "Vuong Nguyen",
159+
"approvedBy": "Vuong Nguyen"
122160
}
123161
]
124162
}

CHANGELOG.md

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,95 @@
11
# Changelog
22

3-
## Unreleased
3+
## 1.5.0 · 2026-09-14
4+
5+
### Added
6+
7+
- **`decision-number-duplicate`** (error): `leji validate` reports two decision records
8+
that carry the same leading number, so a renumbering or a copied record cannot leave
9+
"0017" pointing at two files; padding does not hide it, `0017-a.md` and `17-b.md` are the
10+
same number. Additive, with no change to any existing rule name or severity.
11+
- **`link-unresolved`** (error): `leji validate` now walks the markdown links of every
12+
governed document (the boot profile, every indexed document, the agent profiles, the
13+
decision records) and fails one whose target the layer does not carry, so a rename or a
14+
move cannot leave a dangling reference. Relative targets resolve against the linking
15+
document, a leading `/` against `rootPath`, and a directory passes when it holds a
16+
`README.md`; URLs, `mailto:`, and bare fragments are never judged; a target that leaves
17+
the layer, by `..` or through a symlink, does not resolve. Links inside fenced blocks and
18+
code spans are code. Always on, not behind `--content`. Additive, with no change to any
19+
existing rule name or severity.
20+
- **A set-read guardrail in the scaffolded agent guidance**: the boot profile and core
21+
profile that `leji init` and `leji adopt` write now tell an agent that when one change
22+
introduces two or more decision records, the set is read together before it lands, for
23+
overlap, contradiction, and any record that narrates a state the landed tree will not
24+
show. Existing layers can copy the sentence; nothing rewrites them.
25+
- **`viewer.theme.link`**: an optional manifest field that colors the viewer's body links
26+
and inline code, applied only when it reaches 4.5:1 against the inline-code ground, the
27+
narrower of the two backgrounds those land on. A malformed or too-pale value emits nothing
28+
and warns (`viewer-theme-link-contrast`), so the fixed accessible tone stays; a layer that
29+
sets no `link` renders byte-identically to 1.4.1. Additive schema field, `$id` unchanged.
30+
- **A build marker on source-checkout builds**: `--version`, `-v`, and `version` print
31+
`X.Y.Z+dev.<short-sha>` from a checkout, bare `X.Y.Z` from an installed copy. Released
32+
binaries stay bare: the Go release build stamps a release flag.
33+
- **A generated decisions index**: a layer that declares a decisions category gets a
34+
`_decisions.md` page beside the Manifest page, listing every decision record with its
35+
number, title, status, date, and supersession, all read from the records' own
36+
frontmatter, so no layer maintains a summary table that lags its records. The sidebar's
37+
decisions group links it first and `leji export` carries it into the static site.
38+
- **leji.org in five more languages.** Every prose page, the specification pages, and the
39+
schema reference pages now ship in Spanish, Brazilian Portuguese, Vietnamese, Japanese, and
40+
Simplified Chinese beside the English page of record, with `hreflang` alternates, a
41+
language selector, language-aware navigation and footer, and a translation page that says
42+
how the translations are made and how to report a correction. The specification pages are
43+
informative renderings: the English text stays the only normative one, and a check on every
44+
site build fails if any translation has fallen behind its English source.
45+
- **Japanese and Chinese emphasis renders without Markdown's padding space.** In the Japanese
46+
and Simplified Chinese specification pages, the site's markdown pipeline deletes the
47+
half-width space Markdown forces around emphasis at a boundary between two CJK characters,
48+
so the text reads as the language writes it. Headings, links, and code spans keep their
49+
spaces, and the sources are unchanged.
50+
- **A release-date check on the release path.** `node scripts/version.ts --check --release`
51+
asserts, on top of version coherence, that the `CHANGELOG.md` heading for the declared
52+
version is dated `YYYY-MM-DD` and that the matching `CHANGELOG.json` entry, when present,
53+
names the same day. The pre-publish smoke and the rehearsal run it, so a tag cannot be cut
54+
past an undated heading, and `RELEASING.md` makes the bump and the stamp one release-day
55+
step.
56+
57+
### Changed
58+
59+
- **Sidebar groups follow authored `leji-index` order**: a non-alphabetical index reorders
60+
on upgrade; alphabetizing its entries keeps the previous appearance.
61+
- **The ecosystem scan proves the entry it judged is the entry it reads**, in all three
62+
SDKs. Each manifest and lockfile directly under a root is judged on its own directory
63+
entry, then opened through the verified-source chokepoint, and the descriptor must be the
64+
same regular file a fresh `lstat` of the name reports; the bytes that decide come from that
65+
descriptor. A name retargeted between the judgment and the open is refused rather than
66+
read, while a manifest that is merely unopenable stays unreadable as before; the Python
67+
CLI now takes those bytes from the descriptor too, so its line handling matches the other
68+
two SDKs.
69+
- **Path order is byte order in the TypeScript SDK.** The scans behind the index check, the
70+
sidebar, the decisions page, the agent profiles, and the freshness report sort repository
71+
paths by byte order, as the Python and Go SDKs already did, so a name carrying a character
72+
above the Basic Multilingual Plane orders the same in all three. No fixture's output
73+
changes; only such a name could have ordered differently.
74+
- **The CLI reference says what the commands do.** `adopt` names its `--wire-adapters`
75+
exception; `start` launches from the repository root; `mounts hydrate` no longer claims to
76+
be the only writer of the witness namespace; `export --strict` says the export destination
77+
is what stays untouched. Help output moves with it.
78+
- **Three clarifications on the frozen 1.0 specification line, no requirement changed.**
79+
`conformance.md` states what the boot-profile item's machine check covers (the identity,
80+
loading, and posture headings, reported as a `boot-profile-sections` warning on every
81+
`validate`) and what rides the opt-in content lint; `context-layer.md` requirement 4 and
82+
the manifest schema's `rootPath` description name the viewer's `homepage`, `logo`, and
83+
`favicon` as the one path convention written relative to the context root; `governance.md`
84+
reads "the owner tends the system's health". Every translation follows.
85+
86+
### Fixed
87+
88+
- **The site builds from any working directory.** Pages find the repository by walking up to
89+
`leji.json` instead of assuming Astro's working directory, so `astro build` from the
90+
repository root reads the same schemas and specification as a build from the site package.
91+
92+
## 1.4.1 · 2026-08-26
493

594
A hardening release. The CLI keeps its own generated tree out of git, the viewer takes the
695
brand's typography, the federation commands say which act failed and how to recover, and the

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing
22

3-
The Leji spec is at 1.0, extracted from lived practice; the reference SDKs and tooling are at 1.4.1. The 1.0 spec line is GA and frozen at the v1.3.0 reference-tooling release: schema changes within it are additive only, and breaking changes require a new line per spec/versioning.md.
3+
The Leji spec is at 1.0, extracted from lived practice; the reference SDKs and tooling are at 1.5.0. The 1.0 spec line is GA and frozen at the v1.3.0 reference-tooling release: schema changes within it are additive only, and breaking changes require a new line per spec/versioning.md.
44

55
## Development setup
66

@@ -11,7 +11,7 @@ npm run setup:go # Go: installs goreleaser (the only Go dev tool not bundled wit
1111
npm test # runs the Node, Python, and Go suites
1212
```
1313

14-
Prerequisites: Node 24+, a Python >=3.10 (the Python SDK pins 3.12 via `packages/sdk-py/.python-version`), and Go 1.26.6+. The `setup:*` scripts detect each toolchain and print install hints if it is missing. Both are idempotent and machine-local (the Python `.venv` is git-ignored), so re-run them after cloning or switching machines.
14+
Prerequisites: Node 24+, a Python >=3.10 (the Python SDK pins 3.12 via `packages/sdk-py/.python-version`), and Go 1.26.6+. Node 24 is the development floor, because the repo's TypeScript runs natively on Node's type stripping; the published CLI declares `engines.node: ">=22"` and runs there. The `setup:*` scripts detect each toolchain and print install hints if it is missing. Both are idempotent and machine-local (the Python `.venv` is git-ignored), so re-run them after cloning or switching machines.
1515

1616
**Running your work-in-progress CLI**, two channels, one machine-wide at a time:
1717

@@ -26,7 +26,7 @@ Prerequisites: Node 24+, a Python >=3.10 (the Python SDK pins 3.12 via `packages
2626
- **Pull requests.** Normative changes (anything under `spec/` or `schemas/`) ride PR review and require a `CHANGELOG.md` entry plus a machine-readable `CHANGELOG.json` entry. Yes, the spec dogfoods itself.
2727
- **Contributor terms.** Every commit needs a DCO sign-off (`git commit -s`); contributions ship under the license for their content type. See [Contributor terms](#contributor-terms).
2828
- **Tooling.** SDK changes need tests and must keep `leji validate` passing against `examples/`. The Node, Python, and Go SDKs (`packages/sdk`, `packages/sdk-py`, `packages/sdk-go`) are behaviorally identical: a behavior change in one rides into all three, pinned by the shared `fixtures/` suite. Behavior develops and proves out fully in the TypeScript SDK first, the canonical implementation, against the LIVE channel ([testing-cli-adoptions](docs/practice/testing-cli-adoptions.md)); the Go and Python ports are made only from settled TypeScript behavior, pinned by the shared fixtures at port time. The Go SDK builds with Go 1.26.6+; `gofmt`, `go vet ./...`, and `go test ./...` must pass.
29-
- **Language policy (Node side).** TypeScript + ESM everywhere: SDK source and tests, the site (`astro.config.ts` included), and repo scripts (run natively by Node's type stripping; develop on Node 24+). The one deliberate exception is `packages/create-leji/index.js`, a zero-build published shim. No `.mjs`: every package declares `"type": "module"`.
29+
- **Language policy (Node side).** TypeScript + ESM everywhere: SDK source and tests, the site (`astro.config.ts` included), and repo scripts (run natively by Node's type stripping; develop on Node 24+). The deliberate exceptions are `packages/create-leji/index.js`, a zero-build published shim, with its tests in plain `.js` beside it, and the UI smoke suite's own runners, `packages/e2e/run.mjs` and `packages/e2e/static-server.mjs`. Every package declares `"type": "module"`, so nothing else needs the `.mjs` extension.
3030
- **Style.** Spec prose is plain English, normative keywords per RFC 2119 (MUST/SHOULD/MAY), human-readable first.
3131

3232
## Contributor terms

GOVERNANCE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Leji is an open specification. Its goal is to be an open, vendor-agnostic standa
44

55
## Stewardship
66

7-
Leji was created by Vuong Nguyen. Contexing, LLC is the steward: it maintains the specification, the schemas, the reference tooling, and this repository, and it reviews proposals. Contexing also builds and sells commercial products on Leji; the independence commitments below are what keep the standard independent of those products.
7+
Leji was created by Vuong Nguyen. Contexing, LLC is the steward: it maintains the specification, the schemas, the reference tooling, and this repository, and it reviews proposals. Contexing is also developing commercial products on Leji; the independence commitments below are what keep the standard independent of those products.
88

99
The steward role exists to keep the standard coherent, not to control who uses it. What protects adopters is not trust in the steward's intentions: the complete specification and tooling are openly licensed, run without any steward service, require no steward endpoint, permit competing implementations and commercial services, and can be forked.
1010

0 commit comments

Comments
 (0)