A landlock publication failed with `E409 Failed to save packument` on the
second of three packages. The registry answers a write it could not commit that
way, and publishing several packages back to back is what provokes it.
Neither publish path could recover. The native sequence published from a shell
loop of bare `npm publish` calls: no retry, and no way to resume, because the
registry rejects a repeat of an existing version permanently — so a failure
partway through left the release stuck. publish.ts skipped versions already
present, which made a re-run safe, but had no retry either.
Both paths now attempt a tarball up to four times, space writes at least two
seconds apart, and back off 2s/4s/8s between attempts. Every retry re-reads the
registry first, because a reported failure can answer a write that landed
anyway: a version that now exists with this tarball's integrity counts as
published rather than as one to place again. That same re-read is what turns a
mid-run `E403 cannot publish over the previously published versions` into a
skip when the bytes match, and leaves it a hard failure when they do not.
The native sequence gets the registry comparison publish.ts already had, through
its own script rather than shared code — the two sequences keep separate
publication paths. Its publish job now checks out the repository, which the
shell loop did not need.
Verified against a scripted registry: a clean publish, one E409 then success, an
E409 whose write landed anyway, E409 on every attempt (fails after four), and a
version already present with matching integrity (publishes nothing).
The three release sequences shipped with publishConfig.access: restricted, so
nothing in the @deepseek-ai scope was installable from outside the organization.
A restricted dependency is what actually blocks a public consumer: every harness
package declares the vendored framework as a peerDependency, and
dsh-sandbox-local declares the Landlock entry as a dependency. Those two
sequences therefore go public first — the nine vendor/* packages and the three
native/landlock-run packages — while the dsh family stays restricted until its
own sequence is opened deliberately. No public package requires a restricted one
in this arrangement.
Access is now per sequence, so no publish path can pass --access: one flag
cannot express two levels and would override the manifest that owns the fact.
publish.ts stops passing it, matching the native workflow, and
check-workspace-constraints holds each manifest to its own sequence's level,
which is what stops the scope from drifting one package at a time.
Harness consumers reference the Landlock entry as workspace:^ instead of
workspace:*, so a published harness package accepts the entry's patch and minor
releases. The entry keeps workspace:* for its platform packages, where the
binary must match the entry version exactly.
Two rationales that named a private registry no longer describe the vendored
sequence; they now state the durable reason, which is that the verification must
not depend on the registry already carrying matching versions.
Every package under packages/, apps/, and vendor/ drops "private": true and
declares publishConfig.access "restricted": the repository now states which
packages it publishes instead of deciding it at publish time. Each one also
declares its repository and directory, which is how a consumer of a private
package reaches its source.
The Landlock packages move to restricted with them. They have never been
published, so nothing anonymous depends on them today, and the whole
@deepseek-ai scope stays private.
The workspace constraint that required every package to be private now applies
to non-members only, and asserts the publishable trio on each release member.
Delete design-session citations (decision/audit/plan ordinals, stack
positions), change narration, review choreography, and reviewer-addressed
justification from comments, JSDoc, docs, READMEs, Agent Notes, tests, and
generator templates; restate every affected fact as current-state contract
prose. Fix generated docs at their sources and regenerate the catalogs and
cordis-surface regions; re-paste type-equiv blocks; update every bilingual
counterpart and re-record the pairs. Record the citation rule in the
committed-artifact-citations Agent Note.
Bring the node-addon-landlock-run tree (tag v0.0.1, commit 614f7fd) into
native/landlock-run as its source of record: launcher development happens
here, next to the harness consumers, and the standalone repository becomes
the release mirror the tree is exported to for packing and publishing
(procedure in native/README.md). The subtree keeps its own pnpm workspace
and lockfile and is NOT added to the harness workspace: harness installs,
gates, and CI never touch it. The mirror's .github/ stays out of the
subtree; a separate manually-dispatched workflow
(.github/workflows/landlock-run.yml) runs the subtree's CI legs — the
per-architecture native builds, real-kernel launcher proofs, and pack
rehearsal — adapted with working-directory/cache paths.
eslint ignores the subtree like vendor/; AGENTS.md gains the native/
layout line (+5 words on its budget ceiling).