Repository navigation
Conversation
…er-pro The v5 reference and the 5.4 release notes move to docs/ in HarperFast/harper and HarperFast/harper-pro, so a code PR carries its docs instead of needing a companion PR here. scripts/assemble-content.mjs builds reference/ and the open minor's release-notes page from those trees before every build or dev server start (a local checkout via HARPER_DOCS_PATH / HARPER_PRO_DOCS_PATH, otherwise a sparse fetch of main). The reference sidebar is now autogenerated from front matter and _category_.json files, edit links point at the owning repo, and the deploy workflow checks every 15 minutes whether either repo's docs/ tree changed since the live build. The nested-relationship example tests move to harper, next to the fixture they compare against. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ent guard - The 15-minute source check is its own workflow that dispatches the Pages and Fabric deploys, so it never joins (or cancels) a deploy's concurrency group, and Fabric redeploys too. - The config reads the content manifest per lookup (the dev assembler rewrites it as pages are added) and tolerates its absence for `docusaurus serve` of a downloaded build. - `npm run dev` is the watcher, which starts the dev server itself (no shell `&`). - Assembly refuses to run where reference/ is still tracked, instead of overwriting edits. - PRs run the site build as a Site Build check; preview and deploy path filters track the assembler instead of reference/. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…y, CRLF - The source check skips while a deploy is queued or running, so repeated ticks cannot keep cancelling one that outlasts the interval. - Assembly writes nothing unless both the reference and the release notes assemble. - Front matter with CRLF line endings parses; watcher errors are reported. - The deploy build runs with a read-only token and no persisted credential. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…n watching fails Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
There was a problem hiding this comment.
Code Review
This pull request transitions the documentation repository to an assembled model, where the v5 reference and release notes are dynamically fetched and assembled from the harper and harper-pro repositories during the build process. Consequently, numerous static markdown files have been deleted, and docusaurus.config.ts has been updated to read a generated manifest to dynamically resolve edit URLs and client redirects. The code review identified two critical issues in docusaurus.config.ts where a missing or malformed manifest file, or an undefined reference lookup, could cause the Docusaurus build or startup to crash. Implementing robust parsing and optional chaining as suggested will prevent these failures.
| const readContent = (): ContentManifest => | ||
| existsSync('.content/manifest.json') | ||
| ? JSON.parse(readFileSync('.content/manifest.json', 'utf8')) | ||
| : { reference: {}, releaseNotes: {}, redirects: [] }; |
There was a problem hiding this comment.
If .content/manifest.json is missing, contains invalid JSON, or lacks expected properties (like reference, releaseNotes, or redirects), readContent can throw unhandled exceptions or return undefined for properties, leading to crashes during Docusaurus startup or build. Making this helper more robust ensures smoother local development and CI runs.
const readContent = (): ContentManifest => {
if (!existsSync('.content/manifest.json')) {
return { reference: {}, releaseNotes: {}, redirects: [] };
}
try {
const data = JSON.parse(readFileSync('.content/manifest.json', 'utf8'));
return {
reference: data?.reference || {},
releaseNotes: data?.releaseNotes || {},
redirects: data?.redirects || [],
};
} catch {
return { reference: {}, releaseNotes: {}, redirects: [] };
}
};| } else { | ||
| return `https://github.com/HarperFast/documentation/blob/main/reference/${docPath}`; | ||
| } | ||
| return contentEditUrl(readContent().reference[docPath].repo, `reference/${docPath}`); |
There was a problem hiding this comment.
If readContent().reference[docPath] is undefined (e.g., on a clean checkout or if the document path is not yet in the manifest), accessing .repo directly will throw a TypeError and crash the build. Using optional chaining and falling back to the default repository prevents this crash.
const repo = readContent().reference[docPath]?.repo;
return repo
? contentEditUrl(repo, 'reference/' + docPath)
: 'https://github.com/HarperFast/documentation/blob/main/reference/' + docPath;Docs now merge with the code they describe, so building from main would publish docs for unreleased code. The default source ref is the highest stable vX.Y.Z tag of harper-pro (harper carries the same tag); until a release contains docs/, the site keeps publishing main. content-check compares against the trees that resolution picks (--sources), so a new release redeploys the site. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ted notes Co-Authored-By: Claude Opus 5.5 <[email protected]>
…'s core A release tag is pushed before the release is approved, so the release is now chosen from published releases instead of tags. A docs/<release>-<n> tag in harper-pro publishes a docs correction before the next release. harper's docs come from the commit harper-pro's core submodule points to, the harper that harper-pro was built from, so only harper-pro is tagged. content-check also runs on a docs-source-changed dispatch from harper-pro, with an hourly schedule as the backstop. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…pe the token The release list was read from its first page only; the release is now the highest tag with a published release, one lookup per tag. A docs/<release>-<n> tag without docs/ fails instead of falling back to main, the preview build (which runs PR content with pull-requests: write) no longer gets the token, and content-check runs one at a time. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
⊙ Problem
Since August, 87 of 124 merged documentation PRs were companions to a harper or harper-pro PR, about 90% of them to harper. Each user-facing change takes two PRs, a
companion-checkgate, and a second review.🤔 Should the v5 reference and release notes live in the code repos?
Proposed yes: a code PR then carries its own docs and gets one review. Reverting is three PR reverts.
💡 Solution
docs/in harper and harper-pro.docs/reference/and builds the 5.4 page from one file per change; the sidebar is generated and edit links open the owning repo.corepointer (mainuntil 5.4.0 shipsdocs/); adocs/<release>-<n>tag publishes a correction sooner. Either one triggers a redeploy.learn/,fabric/, the v4 reference and release notes before 5.4 stay here.⚖️ Alternatives
docs/tags are the opt-in version.🔧 Changes
assemble-content.mjsreads each repo from a local checkout or a sparse fetch of harper-pro's latest published release or its highestdocs/tag (mainuntil a release containsdocs/, but never for adocs/tag), with harper at harper-pro'scorepointer or its localcore/, and fails when two repos provide the same page. It collects_redirects.jsonfrom the code repos and builds each open minor's page from fragments, refusing a minor also committed here. It writes nothing unless both parts assemble, and only changed files, so the dev server reloads only edited pages. It publishescontent-sources.json, refuses a checkout that still tracksreference/, and in--watchmode runs the dev server and stops it when watching fails.docusaurus.config.tsreads the assembly manifest for reference edit links, release-note edit links and code-repo redirects, and servescontent-sources.json.sidebarsReference.tsis now one autogenerated entry.content-check.yamlcompares thedocs/trees the assembler would publish with the live site and dispatches both deploys, waiting while a deploy is unfinished. It runs on adocs-source-changeddispatch from harper-pro, and hourly, one run at a time.deploy.yamlbuilds with a read-only token and no persisted credential.deploy.yaml,deploy-fabric.yamlandpr-preview.yamltrigger on the assembler instead ofreference/.validate.yamladds a Site Build check and drops the example-test step.claude-review.ymlandgemini-review.ymltell the reviewers where the reference now lives.package.jsonruns the assembler beforedev,buildandstart, addsjs-yamlfor front matter, and dropstest:examples;package-lock.jsonrecords it..gitignoreignores the generated paths.AGENTS.mdandCONTRIBUTING.mdsay where the reference lives, how to preview a local checkout, and where v5 redirects go.reference/andrelease-notes/v5-lincoln/5.4.mdmove to harper and harper-pro (file list below).nested-relationship-examples.test.mjs,github-fixture-fetch.test.mjsand the fixture copy (github-fixture-fetch.mjs,resources.js,schema.graphql) move to harper, which checks the docs against the integration fixture directly.Moved files (100)
reference/analytics/operations.mdreference/analytics/overview.mdreference/backups/operations.mdreference/backups/overview.mdreference/cli/authentication.mdreference/cli/commands.mdreference/cli/operations-api-commands.mdreference/cli/overview.mdreference/components/applications.mdreference/components/extension-api.mdreference/components/javascript-environment.mdreference/components/module-loading.mdreference/components/nextjs.mdreference/components/overview.mdreference/components/plugin-api.mdreference/components/scheduler.mdreference/configuration/debugging.mdreference/configuration/operations.mdreference/configuration/options.mdreference/configuration/overview.mdreference/database/api.mdreference/database/compaction.mdreference/database/data-loader.mdreference/database/jobs.mdreference/database/overview.mdreference/database/schema.mdreference/database/storage-algorithm.mdreference/database/storage-tuning.mdreference/database/system-tables.mdreference/database/transaction.mdreference/environment-variables/encrypted-values.mdreference/environment-variables/overview.mdreference/fastify-routes/overview.mdreference/full-text-search/configuration.mdreference/full-text-search/overview.mdreference/full-text-search/querying.mdreference/graphql-querying/overview.mdreference/http/api.mdreference/http/configuration.mdreference/http/overview.mdreference/http/tls.mdreference/index.mdreference/legacy/cloud.mdreference/legacy/custom-functions.mdreference/logging/api.mdreference/logging/configuration.mdreference/logging/operations.mdreference/logging/overview.mdreference/mcp/cli.mdreference/mcp/configuration.mdreference/mcp/migration.mdreference/mcp/overview.mdreference/mcp/subscriptions.mdreference/mcp/tool-metadata.mdreference/mcp/tools-and-resources.mdreference/models/analytics.mdreference/models/api.mdreference/models/backends.mdreference/models/calibration.mdreference/models/local-development.mdreference/models/overview.mdreference/models/routing.mdreference/models/tool-calling.mdreference/mqtt/configuration.mdreference/mqtt/overview.mdreference/operations-api/operations.mdreference/operations-api/overview.mdreference/operations-api/sql.mdreference/replication/clustering.mdreference/replication/overview.mdreference/replication/residency.mdreference/replication/sharding.mdreference/resources/overview.mdreference/resources/query-optimization.mdreference/resources/resource-api.mdreference/rest/content-types.mdreference/rest/headers.mdreference/rest/overview.mdreference/rest/querying.mdreference/rest/server-sent-events.mdreference/rest/websockets.mdreference/security/api.mdreference/security/basic-authentication.mdreference/security/certificate-management.mdreference/security/certificate-verification.mdreference/security/configuration.mdreference/security/impersonation.mdreference/security/jwt-authentication.mdreference/security/mtls-authentication.mdreference/security/overview.mdreference/security/response-headers.mdreference/security/secrets.mdreference/static-files/overview.mdreference/studio/overview.mdreference/users-and-roles/configuration.mdreference/users-and-roles/operations.mdreference/users-and-roles/overview.mdreference/web-application-firewall/configuration.mdreference/web-application-firewall/operations.mdreference/web-application-firewall/overview.md✅ Verification
main: all 1,806 pages match, except two code blocks inresource-apithat harper's prettier 3.9 formats differently. Sidebar data, tables of contents and heading anchors are identical.mainwhile v5.3.5 has nodocs/), thedocs/tag pick against a scratch repo (-10over-2,v5.3.50-1excluded), harper from thecorepointer and from a localcore/, dev reload of an added page, CRLF fragments, and a failing fragment that leaves the last assembly intact.format:check,lint,typecheckandtest:workflowspass.Cutover order
Paired with harper#3944 and harper-pro#1237.
mainhere (the migration is scripted), and rebase the hand-written commits.Docscheck fails until step 4, on purpose.Site Buildcheck passes once step 3 is on bothmains.🤖 Generated by Claude Code (Claude Opus 5.5); posted via @kriszyp.
Related PRs: #568 overlaps (each open docs PR here edits a page this PR moves; it is ported to harper or harper-pro after merge), #723 overlaps, #733 overlaps, #744 overlaps, #747 overlaps, #749 overlaps, #750 overlaps, #756 overlaps, #758 overlaps, #759 overlaps, #760 overlaps, #762 overlaps, #772 overlaps, #777 overlaps, #778 overlaps, #779 overlaps, #783 overlaps, #784 overlaps, #786 overlaps, #787 overlaps, #789 overlaps, #780 overlaps (merged; its changes are in the import), #794 overlaps, #795 overlaps, #790 overlaps (merged after the import; the cutover re-import carries it), #791 overlaps (merged after the import; the cutover re-import carries it), #793 overlaps (merged after the import; the cutover re-import carries it)
Complexity: medium
Deferred findings
06b36a0f00f2bf93major reliability —scripts/assemble-content.mjs— default builds throw until upstream docs/ trees land — NOT FILED8b912b9ef6495ad2minor reliability —.github/workflows/content-check.yaml— failed live-manifest fetch is treated as changed and forces a redeploy — NOT FILEDe7033c0d32a1d458minor test-coverage —.github/workflows/validate.yaml— documented-example and fixture-parity tests deleted from this repo — NOT FILED0f199c8b8bae7b2fminor reliability —.github/workflows/content-check.yaml— scheduled workflow auto-disables after 60 days of inactivity — NOT FILED187f9da91d997905nit maintainability —scripts/assemble-content.mjs— _redirects.json entries are not shape-validated at assembly — NOT FILED824a7ddfe2e22248nit reliability —scripts/assemble-content.mjs— Windows shell:true kill leaves docusaurus child orphaned — NOT FILEDf8af58306f549685nit documentation —docusaurus.config.ts— edit links target main while the page shows a release tag — NOT FILED🤔 defer this PR's major reliability finding
06b36a0f00f2bf93(default builds throw until upstream docs/ trees land) to a separate issue instead of fixing it here?Late Grok findings
17 surviving (highest major) — Grok reviewed 92e1979, ruled against 3ba8455
.github/workflows/deploy.yaml:149— Concurrency is split across thebuildanddeployjobs, both withcancel-in-progress: true. Either of two triggers drops newer content: an older run's deploy cancels a newer build, or the next 15-minute schedule tick reads the livecontent-sources.jsonbefore the deploy in flight updates it, (previously adjudicated).github/workflows/deploy.yaml:57— When the curl fetch fails,|| echo '{}'makes the step read it as a change and forces a full build, deploy and skills dispatch. A failedgh apicall turns the job red (previously adjudicated).github/workflows/deploy-fabric.yaml:8— The Fabric deploy has no schedule and does not watchscripts/assemble-content.mjs. Changes todocs/in harper or harper-pro never reach the Fabric production site (previously adjudicated).github/workflows/deploy.yaml:69— Thebuildjob compiles MDX fetched from harper and harper-promainwithout any review in this repo. It sets nopermissions:block, and checkout keeps its credential for later stepsdocusaurus.config.ts:35— The config reads.content/manifest.jsonunconditionally.npm run servefromscripts/preview-pr.mjs, and Docusaurus commands run without the prebuild hook, fail with ENOENT on a clean checkout (previously adjudicated)docusaurus.config.ts:100— The referenceeditUrlreads a manifest captured when the config loads. A reference page added duringnpm run devcauses a TypeError on reload (previously adjudicated)CONTRIBUTING.md:68— This line still tells contributors to runnpm run test:examplesand says the Lint Check job runs it. The script no longer exists (previously adjudicated).github/workflows/validate.yaml:44— The documented-example and fixture-parity tests are deleted, and nothing visible replaces them (previously adjudicated).github/workflows/pr-preview.yaml:6— The preview path filter leaves outscripts/assemble-content.mjsand still listsreference/**, which can no longer change (previously adjudicated).github/workflows/deploy.yaml:30— GitHub disables the cron after 60 days with no repo activity. Reference deploys would then stop with no alert (previously adjudicated).github/workflows/validate.yaml:20— Required PR checks never run the production builddocusaurus.config.ts:36— Edit links always point atmain. An assembled release-note page links to the_index.mdof the repo that supplied the index, even for a paragraph that came from a harper-pro fragment (previously adjudicated)package.json:10— The dev watcher's lifecycle:&under Windowscmd, a watcher left running after Docusaurus exits, nofs.watcherror listener, and assembly errors that are only logged (previously adjudicated)scripts/assemble-content.mjs:95— The front-matter regex only matches\nline endings. On a CRLF_index.md, the front matter goes into the page body andsectionsis ignored. On a CRLF fragment, the build fails with "has no section"scripts/assemble-content.mjs:122— Entries in_redirects.jsonare not shape-checked during assembly (previously adjudicated)scripts/assemble-content.mjs:134—syncFilesoverwrites or deletesreference/files on branches that still track that directory (previously adjudicated)scripts/assemble-content.mjs:141— The added map-shape comment narrates the code below it, anddeploy.yaml:74misstates when cancellation happens (previously adjudicated)Not standing: none. Grok ran 16m (16m from launch to report); the fold adjudication (
cursor-grok@92e197920343-ff2d164f, claude) took 2m.Late Grok findings
1 surviving (highest nit), 10 previously adjudicated — Grok reviewed 67d8f6c
.github/workflows/deploy-fabric.yaml:60— upstream MDX runs duringnpm run buildin the same job that later holdsHARPER_PRODUCTION_PASSWORD(previously adjudicated)scripts/assemble-content.mjs:83— the release list reads only the first page of 100 releases (previously adjudicated)scripts/assemble-content.mjs:133— adocs/<release>-<n>correction tag with nodocs/makes the site fall back tomain(previously adjudicated).github/workflows/content-check.yaml:45— run history is capped at 20 before filtering, so a still-running rerun older than that is missed and the new dispatch cancels it (previously adjudicated).github/workflows/content-check.yaml:53— freshness is checked only against the Pages stamp, so a failed Fabric deploy is never retried (previously adjudicated).github/workflows/content-check.yaml:39— whenDOCUSAURUS_URLis unset,SITE_URLis/and every tick dispatches both deploys (previously adjudicated).github/workflows/content-check.yaml:64— a build that always fails is re-dispatched every hour and on everydocs-source-changedevent (previously adjudicated)scripts/assemble-content.mjs:150— fetching harper at the commit thecoresubmodule pins fails with a raw git error if GitHub can't serve that commitscripts/assemble-content.mjs:150— when thecoregitlink is missing, the failure is a rawgit rev-parseerror instead of themissing()message (previously adjudicated).github/workflows/deploy.yaml:60—GH_TOKENis in the environment of the step that runs upstream MDX (previously adjudicated)scripts/assemble-content.mjs:280— duringnpm run devthe manifest is rewritten in place, so a concurrentreadContentcan parse half-written JSON (previously adjudicated)Not standing: 1 accepted-known. Grok ran 15m (15m from launch to report); the fold adjudication (
cursor-grok@67d8f6c78d51-72d9b2d1, claude) took 1m.Review-Coverage: authored=claude; ran=cursor-composer,gemini,codex,cursor-grok; late=cursor-grok:adjudicated; adjudicated=domain; declined=muse; rounds=9; full=3 @ 5944e16
Review-Attention: deep ~35m (sensitive: content-check.yaml, deploy.yaml; decisions: tags-then-release-by-tag, harper-from-core-gitlink, publish-latest-release-plus-docs-tags, push-plus-hourly-poll, do-less-alternative, deferred-06b36a0f) @ 5944e16