Skip to content

docs(deployment): the install modes page; fix(runtime): the read-only package refusals stop prescribing the retired org overlay - #23108

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-15213-s3-authoring-page
Oct 13, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-15213-s3-authoring-page

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Part of #15213
Clause-②: no

Stage S3 of #15213: the authoring docs page for a package's install modes, and the packages.ts refusal text that still prescribed the retired "ADR-0005 org overlay". S4 (the objectui marketplace choice) remains on the card, so #15213 stays open.

Clause-② is no because only text moves. No accept set, schema, published shape, refusal code, status, details, condition or order changes.

What changes

  • content/docs/deployment/install-modes.mdx (new) and its nav entry in content/docs/deployment/meta.json, right after Publish, Versioning & Preview. Packaging and publishing pages live in that tree, and that page covers the install step this one extends. scripts/docs-audit/handwritten-docs.json was regenerated (check-audit-scope.mjs --write, +1 line).
  • packages/runtime/src/domains/packages.ts: the two read-only refusals name the customisation that works today. One shared clause, CUSTOMISE_BESIDE_REMEDY, serves both doors. The duplicate refusal also names the unmanaged install. The :389 docblock and the duplicate docblock's two remedy sentences were reworded to match.
  • packages/runtime/src/domains/packages-readonly-gate.test.ts: the three pins that read ADR-0005 now read ADR-0131 D6, and they assert that ADR-0005 is absent. The duplicate pin also asserts installMode 'unmanaged'.
  • .changeset/15213-readonly-package-remedy.md: @objectstack/runtime patch.

A1 holds. At 2d21b9c891, git grep -il 'installModes\|unmanaged' over content/docs (excluding releases/ and references/) matched 0 files. The control word os package install matched 7 files on the same tree. No existing page covered install modes, so this is a new page rather than an extension of one.

The page, sentence by sentence, with the code that backs it

Each reading was taken on main before the sentence was written. The suites named here were run at base 2d21b9c89 and again at head 338dc51bf (verification record below).

The two modes (the intro table)

  • A package installs as managed or unmanaged, and the package permits the modes. Backing: ManifestSchema.installModes and INSTALL_MODES in spec/src/kernel/manifest.zod.ts.
  • Managed is registered as code and is the authority. Unmanaged is a copy, written once, and is this environment's own metadata. Backing: the install-local door docblock. Dogfood P1: copied rows have package_id = the base and organization_id NULL, are served _provenance: 'org', and PUT of every copied item answers 200.
  • Managed takes the next version; the copy follows no upgrade. Backing: findConflict answers 'marketplace' (allow upgrade). Dogfood P1: no ledger file, and getPackage(source) is undefined across a restart.
  • Managed keeps the locks; the copy drops them and lists them. Backing: dogfood "lock control" and P1 (below).
  • Managed installs under any posture; unmanaged is refused under group and isolated. Backing: dogfood P2. On isolated the unmanaged install answers 409 UNMANAGED_INSTALL_WALLED_POSTURE with zero writes, and the managed control answers 200.

Declare the modes

  • The defineStack example with installModes: ['managed', 'unmanaged']. Backing: the key is a live manifest key, and manifest.test.ts parses it.
  • Absent means ['managed'], with no parse-time default, so nothing is stamped. Backing: resolveInstallModes and DEFAULT_INSTALL_MODES. manifest.test.ts pins that the parsed output has no installModes property.
  • An empty list is refused, and so is a value other than managed or unmanaged. Backing: .min(1) and z.enum(INSTALL_MODES). manifest.test.ts pins [] and ['template'].
  • unmanaged alone is legal, and a walled deployment cannot install such a package. Backing: judgeInstallMode. A managed request gets 422 INSTALL_MODE_NOT_PERMITTED, and an unmanaged one gets the walled refusal.
  • defineStack, os validate and os build refuse a package that permits unmanaged while carrying certain keys, with STACK_UNMANAGED_INSTALL_UNCOPYABLE and one finding per key. Backing: validateUnmanagedInstallMode in stack.zod.ts and stack-unmanaged-install-mode.test.ts. The keys are:
    • runtime-uncreatable collections (RUNTIME_UNCREATABLE_TYPES, read off allowRuntimeCreate);
    • code (disposition code);
    • other packages' extensions (uncopyable: objectExtensions, picklistExtensions, navigationContributions, contributes);
    • packages (envelope).
  • The fix is to stop permitting unmanaged, or to move what cannot be copied. Backing: the validator docblock's own remedy.
  • The install door judges the same body with the same classification. Backing: UNMANAGED_INSTALL_KEY_DISPOSITIONS in kernel/unmanaged-install.ts, read by both defineStack and the import planner.

Pick the mode at install time

  • --install-mode sets installMode on POST /api/v1/marketplace/install-local. Without the flag no field is sent, and the runtime installs managed. Backing: CLI install.ts:201–:202. The CLI test pins that no installMode is sent without the flag.
  • The refusal table: a mode not permitted gets 422 INSTALL_MODE_NOT_PERMITTED, naming what is permitted; walled gets 409, naming the posture; managed while a copy holds the namespace gets 409 RESOURCE_CONFLICT, naming the base. Each is judged before any write. Backing: judgeInstallMode and step 1f. The cloud-connection install-modes suite covers all three (21 tests), and dogfood P2 and P3 cover them end to end.
  • A runtime that predates install modes installs managed, and the CLI says so and exits 1. Backing: CLI install.ts:297, pinned by the CLI test "asked for unmanaged, answered without it".

What a managed install keeps

  • The install is recorded on the host, registered again at every boot, and a later version installs over it. Backing: the install-local ledger plus kernel:ready rehydrate, and findConflict.
  • A view, dashboard, report, translation or email_template is overlaid by saving one under the same name, and removing the overlay restores the package's own. Backing: the allowEnvironmentOverlay: true registry rows in metadata-plugin.zod.ts. Dogfood managed-content-sealed "control (regime O)": PUT 200, DELETE 200, "reset to artifact default".
  • A flow is switched off or cloned. Backing: the same suite's switch and clone controls, all 200.
  • A save onto any other shipped item is refused, naming its route. Backing: managedItemSealedSentence and packagedBaseRegimeSentence in packaged-base-regime.ts, and the same suite's 403 cases.
  • Locks hold. A protection block is translated into _lock with _lockSource: 'package', the item is served locked with the reason, and the write doors answer 403 ITEM_LOCKED per the lock matrix. Backing: dogfood "lock control" (the dashboard serves lock: 'full', editable: false, deletable: false; the dataset serves _lock: 'no-overlay' and _lockSource: 'package', with no protection). The matrix is objectql/src/protocol-lock-enforcement.test.ts (7 tests).

What an unmanaged copy keeps and drops

  • The copy goes into a new base, PACKAGE_ID-copy, which keeps the namespace. Backing: the door passes no targetPackageId, so planUnmanagedImport uses its default. Dogfood P1 answers targetPackageId: 'com.example.crm-copy' and namespace: 'crm'.
  • Every item goes through the Studio save door, environment-wide, and is served as environment-authored. Backing: importUnmanagedPackage calls saveMetaItem for each item, and dogfood P1.
  • Translations become NAMESPACE_LOCALE items (crm_zh_cn). Backing: the translations: 'converted' disposition, the unit test, and dogfood P1.
  • Sample data is not loaded, and the answer says seeded.mode: 'skipped' when the package declares any. Backing: installUnmanaged (declaresSeeds) and dogfood P1.
  • Nothing is registered under the source id; a later managed install is refused, and so is a second unmanaged install. Backing: dogfood P1 and P3.
  • All or nothing: refusals come before the base exists, a name collision included, and a failed write deletes the base. Backing: the importUnmanagedPackage steps 1–8 and rollBackUnmanagedImport. Unit tests cover the environment-row collision, the managed-name collision and the mid-copy failure.

The copy keeps no lock, in either spelling (the seat's carry 6128999134, restated in 6132465308)

  • The reason paragraph paraphrases ruling A on [Decision] 「非托管」安装复制带 _lock 的打包项时:去掉锁(A)、拒绝这类包(B),还是原样保留锁(C)?(ADR-0131 D6 × ADR-0010 保护模型) #22971 (6119681934): "a package permits unmanaged explicitly through installModes, so the vendor has already chosen to let environments take editable copies".
  • Each copy is written without _lock, _lockReason, _lockSource and _lockDocsUrl, and without its protection block on a type whose schema declares one. Backing: stripUnmanagedImportLock. The block's declaration is asked of overlaySchemaDeclaredKey. Dogfood P1 finds no copied row carrying any of the five keys.
  • Every copied item is served unlocked, and its next save is accepted. Backing: dogfood P1, including the three locked fixture items.
  • A lock value the declarations refuse is not stripped, and the save door answers 422 INVALID_METADATA with a rollback. A protection block on action, hook or page is left in place and refused the same way. Backing: unit tests "a lock family the spec refuses is not stripped" and "a protection block on a type that declares none is still refused by the save door".

The install lists each lock it drops

  • strippedLocks has one entry per binding lock, in write order, shaped { type, name, lock, reason? }. reason is verbatim, or absent when the package gave none. Both spellings on one item produce one entry with the block's lock. none is not listed. The list is always present. Backing: ImportUnmanagedPackageResponseSchema.strippedLocks and the unit tests for both spellings, none, and a package that locks nothing. Dogfood P1 checks the exact list.
  • The CLI prints Locks removed, then one TYPE.NAME: LOCK — REASON line per lock, leaving off the dash and reason when there is no reason. Backing: CLI install.ts:275–:283. The CLI test pins Locks removed:\s+2 and both line forms. The printed block mirrors printKV's layout.
  • "Choosing what to permit" applies the ruling: there is no "copy, but keep the lock" mode (ruling A's fallback B is unbuilt).

The remedy text, FROM → TO

WRITABLE_PACKAGE_REQUIRED (DELETE, PATCH /disable, POST /publish, POST /revert on a read-only package)

FROM:

… — ACTION a package you own, or customise what this one provides in place, with an ADR-0005 org overlay.

TO:

… — ACTION a package you own, or customise what this package provides beside it, as environment-level state (ADR-0131 D6): save an item under its own name — that overlays it where the item's type takes an environment overlay and the package's lock does not refuse it, and is otherwise refused naming the route that type has, or the lock.

DUPLICATE_SOURCE_NOT_A_BASE (POST /packages/:id/duplicate on a read-only package)

FROM:

… Duplicate a base you own, or customise what this package provides in place, with an ADR-0005 org overlay.

TO:

… Duplicate a base you own, or customise what this package provides beside it, as environment-level state (ADR-0131 D6): save an item under its own name — that overlays it where the item's type takes an environment overlay and the package's lock does not refuse it, and is otherwise refused naming the route that type has, or the lock. For an editable copy of the whole package, install it unmanaged instead (installMode 'unmanaged'), where its manifest's installModes permits that.

Why each remedy, measured on main:

  • The org overlay is dead. Every write that names an organization is refused 403 NOT_OVERRIDABLE by organizationScopedWriteRefusal. protocol.org-scoped-write-refused.test.ts pins it for every registry type, on the save, the publish and the package publish. Together with the unmanaged-install suite it passes 364 tests at head.
  • Customising beside the package works.
    • Environment overlay: the regime O control saves and removes an overlay of a packaged view.
    • Flow switch and clone: both answer 200.
    • Any other sealed item is refused with the route its type has: managedItemSealedSentence.
    • A locked item is refused with its lock and reason: ITEM_LOCKED, per the matrix test.
  • The unmanaged install covers the duplicate gesture's intent, an editable copy of a package.
    • It works where the package permits it: dogfood P1.
    • It is refused loudly otherwise, each refusal before any write:
      • a mode the package does not permit gets 422 INSTALL_MODE_NOT_PERMITTED;
      • a walled posture gets 409;
      • a managed install of the same package holding the namespace gets 409 RESOURCE_CONFLICT with "Uninstall that package first, or keep the managed install" (unit test "refuses an owned namespace — a managed install of the same package included").
    • "Instead" in the sentence carries that last condition.
  • A2 holds. There were 3 hits for the retired remedy at 2d21b9c891 (:389, :538, :641) and 0 at head. No refusal is left without a working remedy, so there is no open question.

Verification record

At head 338dc51bf, the merge of origin/main abf86554c through scripts/pm/os-regen-merge.sh. The merge left no further changes to commit, and the branch touches no generated artifact that needs regeneration. The dogfood closure was rebuilt on the merged tree: turbo run build --filter=@objectstack/dogfood^..., 63/63, through os-verify-lock.sh. Every run below went through the lock, and each VERDICT line reads exit 0. The reading-suite chain is joined with && after one leading export, so its last exit covers every suite in it. The reverse-verification script exits 0 by design, and the red it measured is quoted below.

  • @objectstack/runtime, the affected package. Full vitest run --project local: 361 files, 5163 passed, 19 skipped. typecheck exit 0.

  • The reading suites, at head:

    • metadata-protocol package-unmanaged-install.test.ts + protocol.org-scoped-write-refused.test.ts: 364 passed;
    • objectql protocol-lock-enforcement.test.ts: 7;
    • cli --project unit package-install-mode.test.ts: 10;
    • cloud-connection marketplace-install-local-install-modes.test.ts: 21;
    • spec stack-unmanaged-install-mode.test.ts + kernel/unmanaged-install.test.ts + kernel/manifest.test.ts: 103;
    • dogfood install-local-unmanaged-mode + managed-content-sealed: 30.

    The same suites, minus the org-scope and lock-matrix files, passed at base 2d21b9c89 before the page was written.

  • Reverse verification, from the committed state:

    • packages.ts was restored from base 2d21b9c891 (blob aad47d51d5, landing proven by hash equality; "ADR-0005 org overlay" ×3, CUSTOMISE_BESIDE_REMEDY ×0).
    • packages-readonly-gate.test.ts then went red as predicted: 3 failed, 22 passed. The three failures were the duplicate envelope pin and the DELETE and disable remedy pins.
    • It was restored with git checkout HEAD -- under an EXIT/INT/TERM trap. Afterwards the blob equals HEAD (fd665ab7e8) and git diff HEAD is empty.
  • Gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack was derived at 338dc51bf. Its stderr line 1 names objectstack-ai/objectstack at 338dc51bf, and it derived 100 commands. One pass ran at 338dc51bf, with HEAD recorded before and after and stdin closed:

    • 97 exit 0.
    • pnpm check:type-check-debt: skipped, NOT MEASURED by the dispatch.
    • pnpm --filter @objectstack/spec run check:skill-examples and pnpm check:dual-build-cjs-loads: exit 3, PREREQUISITE NOT MET. They need dist/ of packages this diff does not touch: client-react, studio, embedder-openai, knowledge-memory, knowledge-ragflow, organizations, service-cluster-redis and service-knowledge. Three tries to build them through the lock each hit queue-timeout (exit 99, about 27 minutes, while another run held the lock). This is a declared narrowing: NOT MEASURED here, and CI runs both.
    • --ran reconciliation: 100 derived, 97 run, 2 NOT-MEASURED, 1 UNRUN (check:type-check-debt, as dispatched).
    • The named docs gates, all exit 0: check:doc-authoring; check:doc-anchors (491 fragment links resolve); check-affected-docs; check:docs-audit-scope (203 hand-written docs); check-doc-frontmatter (414 pages parse); check:docs-single-h1; @objectstack/spec check:docs. check:nul-bytes exit 0 too.
    • check:generated is not derived for this diff, which touches no spec file.
    • The link lane is NOT MEASURED. lychee runs in an advisory CI lane and is not installed here. The page's five internal link targets and its two ADR files exist on disk.
    • Lint, narrowed. eslint's config matches 2 of the 6 changed files, packages.ts and its test. The .mdx, the .md and the two .json files answer "File ignored because no matching configuration". eslint --no-inline-config --format json on the 2 files reports 2 files, 0 errors and 0 warnings. The config enables no type-aware linting (no parserOptions.project, no projectService; 6 rules resolve for packages.ts), so this diff cannot move a verdict on an untouched file.
    • Docs re-read. affected-docs.mjs origin/main names content/docs/api/metadata-api.mdx (re-read: it quotes neither refusal's text, so nothing changes) and one release-owned page.
  • Size: 322 changed lines (+299 / −23), 6 files, against merge base abf86554c. Under the 3,000 human-merge line.

Acceptance notes

  • S2's carry on package-lifecycle.zod.ts:233 (A3) is not applied here. PR feat(spec, metadata-protocol): the draft list and the commit timeline tell two languages of one email template apart — each entry carries member (#23073) #23099 (claude/issue-23073-list-member, another seat) edits that file and is open and not merged, so this stage does not touch it.
  • The CLI reference does not list --install-mode. content/docs/deployment/cli.mdx, the os package install options table, has no row for the flag S2 shipped. Neither Publish, Versioning & Preview (step 3) nor the deployment index table ("The pages for shipping an app") links the new page. All three are outside this claim's file surface (one new page plus its nav entry). Carrier: none.
  • The installModes TSDoc names the wrong code for the authoring refusal. spec/src/kernel/manifest.zod.ts (:628) says UNMANAGED_INSTALL_UNCOPYABLE. defineStack raises STACK_UNMANAGED_INSTALL_UNCOPYABLE; the shorter code is the import's. It is TSDoc only and does not reach the generated reference. Carrier: none.
  • packaged-base-regime.ts says the install mode is not modelled yet. Its header (the "A managed package" section) reads "The install mode is not modelled yet (the manifest declaration of permitted modes is later work)", which has been stale since S2. Its conclusion still holds: only a managed install registers items through the artifact loader. Carrier: none.
  • ADR-0126's status line still spells the mode template. S2's ACCEPT routed this to S3. It is Tier H and outside this claim's file surface, so it is not edited. Carrier: none.
  • The page does not cover an unrecognised posture value. It names only group and isolated for the walled refusal. The verb reads an unrecognised OS_TENANCY_POSTURE as walled, but S2 observed the door's admission answering 401 before that point in a stub harness. That is unmeasured here, so the page does not state it.
  • No real package declares installModes yet. git grep -l installModes -- examples matches 0 files at head. The control manifest: matches examples/app-crm and examples/app-multi-package on the same tree. The page's guidance is prospective, and only the dogfood fixture adds the key.

Generated by Claude Code

…hat works, not the retired org overlay

WRITABLE_PACKAGE_REQUIRED and DUPLICATE_SOURCE_NOT_A_BASE prescribed "an
ADR-0005 org overlay". ADR-0131 D6 retired that axis: a write naming an
organization answers 403 NOT_OVERRIDABLE. Both now name customising beside
the package as environment-level state, one clause shared by the two doors;
the duplicate refusal also names the unmanaged install for an editable copy.
Text only: no code, status, condition or order changes.

Claude-Session: https://claude.ai/code/session_019G5ZnRrTMiwcHG6iZM19zf
Co-authored-by: Claude <[email protected]>
…ed install keeps, and what an unmanaged copy keeps and drops

A new authoring page beside Publish, Versioning & Preview: how a package
declares installModes, how the installer picks a mode, what a managed
install keeps (its locks bind), and what an unmanaged copy keeps and drops
(no lock in either spelling; strippedLocks and the CLI's Locks removed
lines name each one). Plus the runtime changeset for the refusal text, and
the regenerated hand-written docs list.

Claude-Session: https://claude.ai/code/session_019G5ZnRrTMiwcHG6iZM19zf
Co-authored-by: Claude <[email protected]>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Oct 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/runtime, touching 5 documentable anchor(s).

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/metadata-api.mdx (via /packages/:id/duplicate (route, a path literal in a comment on a changed line))

⛔ 1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-4.mdx (via /packages/:id/duplicate (route, a path literal in a comment on a changed line))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 26 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 2808438e9dad471383140b286f8d970afa59559d → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 99889f878e5867e5050b30d4e36b371ae4c3259b — the merge of head 338dc51bfd73f4e8ece5d3d3b2bedeaded33a6cb into base 2808438e9dad471383140b286f8d970afa59559d, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 99889f878e5867e5050b30d4e36b371ae4c3259b && git checkout 99889f878e5867e5050b30d4e36b371ae4c3259b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 2808438e9dad471383140b286f8d970afa59559d 338dc51bfd73f4e8ece5d3d3b2bedeaded33a6cb && git checkout -B drift-repro 2808438e9dad471383140b286f8d970afa59559d && git merge --no-ff 338dc51bfd73f4e8ece5d3d3b2bedeaded33a6cb

node scripts/docs-audit/affected-docs.mjs --json 2808438e9dad471383140b286f8d970afa59559d

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 2808438e9dad471383140b286f8d970afa59559d → pass the list as
args.docs, on the commit named under Which tree this was computed on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants