Skip to content

docs(adr): ADR-0025 v2 says what M1 shipped — the local install loop, the trusted-key store, the native-addon refusal, manifest-deps retired (#27684) - #27815

Merged
os-zhuang merged 4 commits into
mainfrom
claude/project-thread-azb7h4
Oct 30, 2026
Merged

os-zhuang merged 4 commits into
mainfrom
claude/project-thread-azb7h4

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Elon · project thread

domain:skills#2 · os-elon-musk · session_016WV4d1j1VPnYjVUvuUMHjc

Fixes #27684

Ruling-ref: 6467932167
Clause-②: no
Metadata-protocol: none

维护者速读

What changes

One file, docs/adr/0025-plugin-package-distribution.md (+45 / −33). Every replacement sentence was measured on origin/main f5dd0575; line numbers below are on that commit unless marked.

The eight edits the card lists:

# Where Was Now Evidence
1 §3.5, the M1 bullet the plan ✅ landed 2026-10-29 (#27335, #27374, #27679), what each step does, and the acceptance run on the cloud Stripe sample still open (#27570) install.ts header steps 1–6; installed-plugin-loader.ts header checks 0–5; plugin-installation-store.ts header (local stand-in for the sys_package_installation row); disable.ts, uninstall.ts headers; #27570 open, status:parked, domain:cloud
2 §7, key management deferred to M3 + a dated note, as ruling 6467932167 ordered: the trusted-key store landed in M1 in its minimal form; rotation and the platform / cloud sources stay M3 packages/platform-objects/src/system/sys-trusted-key.object.ts (source select local / platform / cloud, status active / revoked); packages/cli/src/commands/plugin/keygen.ts; trust/{add,list,revoke}.ts; install refuses an unknown or revoked key id (install.ts header step 1), the loader too (signature_key_untrusted, signature_key_revoked)
3 §3.5, "Steps 4–7 do not exist … there is no os plugin install" false steps 4–7 exist for a local artifact only (step 7's per-plugin enforcer is M2); in the cloud nothing serves the .osplugin back install.ts exists and takes a file path only (Args.string, "Path to the .osplugin artifact"); §3.4's download-route sentence is unchanged and still true
4 §3.2, // bundled | manifest-deps stale // bundled, the one strategy manifest.zod.ts:258 enumWithRetiredValues(['bundled'], PACKAGING_RETIRED)
5 §3.3, "the build does not yet refuse them mechanically (M1 adds the refusal)" false os plugin build refuses a native addon before writing anything build.ts:303 findNativeAddons and the refusal, before computeIntegrity; the only writes are build.ts:331–332, after it; esbuild runs with write: false (build.ts:271)
6 §3.3, "the build-side half is removed in M1" future tense done: the schema refuses manifest-deps by name with its prescription; M1 (#27679) removed the build half manifest.zod.ts:238–258 (PACKAGING_RETIRED); build.ts header step 2 (everything but @objectstack/* inlined)
7 §3.5 step 5, "For manifest-deps, run pnpm install … here" stale v2: nothing is installed there; install runs no package manager install.ts header: verify, read, re-verify integrity, materialize, record; no package-manager call in install.ts
8 §5 Negative, "mitigated by the opt-in manifest-deps strategy in Phase 5" false the build refuses native addons; with manifest-deps retired a plugin that needs one waits for M3 (§3.3) §3.3's own retirement paragraph; build.ts:303

Three more in the same file, same defect class (made false by slices 1–3), fixed in place under os-dev's bounded in-place rule and agreed by the seat before the edit (claim 6511498060's file-surface line names them):

# Where Was Now Evidence
9 §3.6 v2 paragraph "nothing dispatches on the tier at load"; "Until M3, the publish-time refusal is the only tier gate" the boot-time loader dispatches (node imported in process; sandbox / worker and an undeclared tier refused by name); until M3 nothing loads isolated installed-plugin-loader.ts:180–195 dispatchPluginRuntime (runtime_undeclared, runtime_not_dispatched); manifest.zod.ts:214–222 describe; listed as owed in the slice-2 hand-over 6496079064
10 §3.4 step 2 "verifyPluginArtifact … has no production caller until M1 (the loader checks only that a signature is well-formed)" install and every boot verify against the environment's trusted keys; plugin-loader.ts refuses a signature no host verified install.ts:254 verifyPublisherSignature; installed-plugin-loader.ts:341 verifyPluginArtifact; plugin-loader.ts:519–552
11 Status line M1 listed under "Not yet built" M1 listed under what landed (acceptance run still open); the cloud fetch stays M2, tier dispatch beyond node stays M3; "amended 2026-10-30 to what M1 shipped" the three merged PRs above; docs/adr/README.md index cell unchanged (adr-index --check OK)

Kept as written, because they correctly record the retirement: the v2 note (L15), the artifact tree (L141–142), the §3.3 RETIRED bullet head, the Q6 row, the §4 M1 phasing bullet and the Phase 5 mapping line.

Tests

None: an ADR text change, no code and no tested behaviour, so no ablation.

Acceptance notes

Verification

Head c49a117f. Local subset = every family node scripts/pm/dispatch-gates.mjs --commands derives for this diff (21), re-run on the final head; the lint closure was built first for check:doc-formula-expressions.

dispatch-gates: 21 derived, 21 run, all exit 0
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm check:adr-anchors :: exit 0
pnpm check:adr-index :: exit 0
pnpm check:adr-symbol-anchors :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-prior-rulings :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:watch-hint-literal :: exit 0

dispatch-gates --ran: "21 derived famil(ies) accounted for — 21 run, 0 NOT-MEASURED (a DERIVED zero — all 21 recorded an exit code and none of them is 3)."

Other readings
  • node scripts/adr-index.mjs --check: "OK — docs/adr/README.md is current and every record parsed." (the index cell is cut before the status-line text this PR changes).
  • node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD: both commits clean.
  • dispatch-gates --tier: MANDATORY docs/adr/** ceiling tier; this draft was written at the default tier on the seat's recorded downgrade, and the contract review at the ceiling tier is owed before any approval is asked.
  • Changed lines 78 (+45 / −33), under the 3000 human-merge threshold.
  • Card re-check on the head: grep -n "manifest-deps\|Steps 4–7\|M1 adds" docs/adr/0025-plugin-package-distribution.md hits L15, L141–142, L188, L192, L295, L560, L567, L582, L603 — each one either records the retirement or is a corrected line.

Generated by Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_016WV4d1j1VPnYjVUvuUMHjc

… the trusted-key store, the native-addon refusal, manifest-deps retired

Slices 1-3 of the M1 local T0 install loop landed, and the record still
described the code before them. Corrected in place, history kept:

- Status line: M1 moves from "not yet built" to what landed; the cloud
  fetch stays M2, tier dispatch beyond node stays M3.
- 3.2: the packaging comment names bundled as the one strategy.
- 3.3: os plugin build refuses a native addon; PluginPackagingSchema
  refuses manifest-deps by name; the build-side half is gone.
- 3.4 step 2: install and every boot verify the signature against the
  environment's trusted keys; plugin-loader refuses an unverified one.
- 3.5: step 5 runs no package manager; steps 4-7 exist for a local
  artifact; the M1 bullet is a landed line, its cloud-sample acceptance
  run still open.
- 3.6: the boot-time loader dispatches on the tier (node imported,
  sandbox / worker / undeclared refused by name).
- 5: the native-addon risk no longer names a manifest-deps mitigation.
- 7: the dated note the B-prime ruling ordered — the trusted-key store
  landed in M1 in its minimal form; rotation and platform / cloud
  sources stay M3.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4d1j1VPnYjVUvuUMHjc
…eside the local steps 4-7

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4d1j1VPnYjVUvuUMHjc
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 30, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Oct 30, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract-review-claim: session_016WV4d1QkPVVzNz3FJqb2iS · head c49a117 · 2026-10-30T00:33Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: c49a117fc4e5231719a6eb2a1e52dd3ea7539b8c
Local-runs: none
Scope: docs/adr/0025-plugin-package-distribution.md + packages/cli/src/commands/plugin/install.ts, packages/cli/src/commands/plugin/build.ts, packages/cli/src/commands/plugin/keygen.ts, packages/cli/src/commands/plugin/trust/{add,list,revoke}.ts, packages/cli/src/commands/plugin/{disable,enable,uninstall}.ts, packages/cli/src/utils/plugin-trust-read.ts, packages/cli/src/utils/installed-plugins-boot.ts, packages/cli/src/commands/serve.ts (the boot call only), packages/core/src/plugin-loader.ts, packages/core/src/security/plugin-artifact-signature.ts, packages/core/src/security/plugin-artifact-verdict.ts, packages/runtime/src/installed-plugin-loader.ts, packages/runtime/src/plugin-installation-store.ts, packages/spec/src/kernel/manifest.zod.ts, packages/platform-objects/src/system/sys-trusted-key.object.ts, docs/adr/README.md — all read on main at f5dd05758 (the PR's parent commit and the dev's measuring tree; the nine main commits since touch none of them, read off the compare endpoint).

Inputs: card #27684 body and its three comments (triage 6504395881, claim 6511498060 with the amended file-surface line naming items 9–11, os-dev-report 6511915566); #27123 body, carry-over 6484915007, hand-over 6496079064, ruling 6467932167 (letter B′), the slice-3 contract review 6504145955; PR #27815 body, file list (one file, +45/−33) and the net diff of its two commits against f5dd05758; the check-runs on the head. The clone's origin/main ref is stale at e00374a3, so the three-dot diff the brief names picks up two unrelated main commits — the net diff judged is f5dd05758..c49a117f, which is exactly the PR's one file. Reviewed adversarially: the tree, never the body's account of it.

Tier. docs/adr/** is a Tier H register row: the maintainer's hand lands this PR, and this record is the compensating control the claim recorded for the seat's tier downgrade, not an approval. Draft, no auto-merge, no requested reviewer, Governed Surface Queue Guard success. The PR carries no assignee while the card's is os-elon-musk — the executor's pr_create set none (report deviation 3); the seat's relay act, not a tree matter.

Check-runs at this reading. 46, all completed: 26 success, 20 skipped, 0 failed, none running. The required contexts: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (all eight shards), Governed Surface Queue Guard success, Test UI success; Build Core, Lint UI, Type Check UI, Build & E2E UI, Live E2E UI skipped by the path filter (filter success) on a one-file docs diff. Also green: Check Changeset, Check Documentation Links, Check PR Size, every Lint · and Type Check · lane (the lanes carrying check:adr-links, check:adr-index, check:adr-anchors, check:doc-authoring).

① Derived judgments

The diff is one Markdown file under docs/adr/. It changes no Zod schema, no accept set, no export, no generated artifact, no gate and no governed register row; docs/adr/README.md's index cell for ADR-0025 is cut before the first changed character of the status line (verified on f5dd05758, check:adr-index green on the head). None derived — right.

② Semver level

  • Clause-②: no on the PR body — right: no authorable key or value moves.
  • Metadata-protocol: none — right.
  • No changeset; skip-changeset label set at creation; Check Changeset success. Right: the diff publishes nothing — docs/adr/** ships in no npm tarball, and the Post-Task Checklist's changeset duty attaches to a published package moving.

③ Boundary flags

os-dev-report 6511915566 open_questions: none. Every deviation and every cited open item, answered:

④ Design judgment

The ADR against its first consumer (the M1 slices: #27335 install + trusted-key store, #27374 boot-time loader + disable / enable / uninstall, #27679 bundled-only build + native-addon refusal), its execution plan (#27108 M0–M3, §4) and the ruling it records (6467932167, B′). Every sentence the diff writes, read against the cited code on f5dd05758:

  • Status line. "M1, the local T0 install loop (2026-10-29, §3.5: os plugin install ./x.osplugin against the environment's trusted keys, the boot-time loader with the tier dispatch point, disable / enable / uninstall; its cloud-sample acceptance run is still open)" — each clause holds (install.ts header steps 1–6; installed-plugin-loader.ts header checks 0–5; disable.ts, enable.ts, uninstall.ts; plugin install acceptance e2e on cloud plugins/connector-stripe: build, sign, install, boot, one tool, disable, tamper cases (#27123 item 6) #27570 open). "Not yet built: the cloud fetch (M2), runtime enforcement of the granted set (registered only today, §3.7 — M2), tier dispatch beyond node (M3), publish-side scans and secret-refs (M3)" — consistent with §3.5 M2, §3.7 v2, §3.6 v2 and §4. Holds. Should-fix (prose): the amendment list "(§3.3, §3.4, §3.5, §3.6, §7)" omits §3.2 (the L159 packaging comment) and §5 (the L602–603 risk), both edited by this diff; the status line is the ADR's own changelog and should name all seven.
  • §3.2 L159 // bundled, the one strategy (see §3.3) — PluginPackagingSchema = enumWithRetiredValues(['bundled'], PACKAGING_RETIRED) (manifest.zod.ts:258). Holds.
  • §3.3 bundled bullet. "since M1 os plugin build refuses one before writing anything (a .node module or a native package the bundle reaches, or a .node file under assets/)" — build.ts:271 esbuild write: false, :303 findNativeAddons(metafile, cwd, assets) and the exit-1 refusal at :304–313, computeIntegrity at :316, the only writes at :331–332; the three signals are the header's step 3 and findNativeAddons (.node in the graph, binding.gyp / gypfile: true / shipped .node, assets/*.node). Holds.
  • §3.3 RETIRED bullet. "PluginPackagingSchema accepts bundled only and refuses manifest-deps by name with its migration prescription; the build-side half was removed in M1 (feat(spec, cli)!: bundled is the one plugin packaging strategy — manifest-deps is retired, and os plugin build refuses a native addon (#27123, slice 3 of 3, server half) #27679)" — manifest.zod.ts:238–258; build.ts header step 2 and :259–275 (external: ['@objectstack/*'], everything else inlined). Holds.
  • §3.4 step 2. "Since M1 the host verifies it against the environment's trusted keys (§7) at os plugin install and again at every boot (verifyPluginArtifact); plugin-loader.ts refuses a signature no host verified" — install: install.ts:220 readTrustedKeys, :254 verifyPublisherSignature over the raw bytes; boot: installed-plugin-loader.ts:341 verifyPluginArtifact with requirePlatform: false; plugin-loader.ts:519–556 reads the WeakMap verdict (plugin-artifact-verdict.ts) and throws on a signature with no recorded verdict for that exact string. Holds. Observation, no finding: the parenthetical names the loader's function; install calls verifyPublisherSignature, which verifyPluginArtifact:283 wraps — as placed (after "at every boot") it reads right.
  • §3.5 step 5 v2. "nothing is installed there; bundled is the one strategy (§3.3), so install runs no package manager" — install.ts steps 1–6: verify, read, re-verify integrity, lock, materialize, record; no package-manager call anywhere in the file. Holds.
  • §3.5 "Steps 4–7 exist for a local artifact only (M1, below; step 7's per-plugin enforcer is M2, §3.7). For a code plugin in the cloud they do not: nothing serves the .osplugin back (§3.4)…" — install.ts:117 takes a file path only (Args.string, "Path to the .osplugin artifact"); §3.4 L242–245 (unchanged) still records the download route as M2; §3.7 v2 (unchanged) still records SecurePluginContext as M2. Holds and is internally consistent.
  • §3.5 ✅ M1 line, clause by clause: "verifies the .sig over the raw bytes against the environment's trusted keys (§7) before inflating anything" — install.ts:150–272 runs before readTarGz at :277. "re-verifies every file against integrity" — :339 verifyIntegrity (mismatch, missing, undeclared each refused). "materializes to OS_HOME/plugins/env/id/version/" — pluginInstallDir (plugin-installation-store.ts:8). "records the install in a local store (the stand-in for the §3.8 row)" — :393–408; the store header L17–21 says exactly that. "--trust-unsigned admits only an unsigned artifact, loudly" — :196–218 (a present signature is always verified, printStep says the flag has no effect) and :320–325 printWarningToStderr. "At boot … os serve re-verifies each install (artifact sha, signature, byte-equal tree), dispatches on the tier (§3.6) and hands what passed to kernel.use, which orders dependencies" — serve.ts:13 imports registerInstalledPlugins; loader checks 2, 3 (:322–348, before readTarGz at :353), 4 (:350–389), 5 (:392); installed-plugins-boot.ts:131 kernel.use, header L27–28 "dependency order and health checks are the kernel's". "os plugin disable / enable use the package disable-state store" — disable.ts header L7–9, installedPluginDisabledIds / setInstalledPluginDisabled. "uninstall takes effect at the next boot" — uninstall.ts header L6–12, markPluginUninstall; loadInstalledPlugins:668–691 finishUninstall. "Still open: … (objectstack#27570)" — open, parked. Holds, every clause. Observation, no finding: an artifact whose manifest carries no integrity map installs with the per-file check skipped and reported (:460–462); os plugin build always writes the map (:316–317), so the sentence holds for every built artifact and the signature still covers the bytes.
  • §3.6 v2 paragraph. "since M1 the boot-time loader dispatches on an installed plugin's tier (dispatchPluginRuntime): node is imported in process, sandbox / worker and an undeclared tier are refused by name — every plugin that loads today loads in-process … Until M3 nothing loads isolated (those tiers are refused, not confined)" — installed-plugin-loader.ts:180–200 (runtime_undeclared for unset / null / empty, runtime_not_dispatched otherwise, no fallback); manifest.zod.ts:200–212 says the same and that a stack's own plugins entry is not dispatched, which "loads in-process" covers. Tried to break it: install.ts:435 also dispatches at install time (a warning, not a refusal) — the ADR names the loader as the gate, which is where the refusal is; no contradiction. Holds.
  • §5 Negative. "Bundled packaging excludes native addons, and os plugin build refuses them; with manifest-deps retired (Q6), a plugin that needs one waits for M3 (§3.3)" — §3.3's own last sentence; build.ts:303. Holds.
  • §7 dated note against ruling 6467932167. "sys_trusted_key (public keys only, source: 'local'), os plugin keygen and os plugin trust add | list | revoke; install and boot refuse an unknown or revoked key id by name" — sys-trusted-key.object.ts (public_key SPKI PEM, source select local / platform / cloud with local the only writer, status active / revoked, revoked never re-activated); the four commands exist with the ruling's semantics (trust/add.ts refuses a private-key PEM by name); install.ts:226–241 signature_key_untrusted / signature_key_revoked; loader :325–330 the same two. Holds. Should-fix (the one finding of substance): "Rotation policy and the platform / cloud sources stay M3" copies the ruling's ordering sentence, but the ruling's own body places the cloud rows in M2 ("M2's chain is root key → platform counter-signature → publisher key, cached as source: 'cloud' rows in this same store"), the object's docblock written under that ruling says "platform and cloud for the keys M2 / M3 cache from that chain", and the ADR's own §3.5 M2 bullet has the download route serving the artifact "with publisher + platform signatures" — which needs those rows. The note should say what the ruling's body and the code say: rotation policy M3; platform / cloud rows reserved, written by the M2 chain (cloud) and M3. A phasing label on unbuilt work, so not a must-fix; one clause, respin or a follow-up.

No remaining sentence contradicts the corrected ones in the as-built layer: the §7 Q8 answer ("boot activation only"), §3.7 "Reversible disable … on next boot", §3.5 step 6 (local store, package-state-store.ts pattern), §3.4 L242–245 (download route M2), §3.7 v2 (SecurePluginContext M2), §4 Q3 / Q6 / Q8 and the M1 phasing bullet (the plan, kept as the plan) all agree with the new text. The ✅ line's "hot reload was retired with #12587" agrees with §7. No must-fix.

Pre-existing original-design sentences M1 made stale — not in this diff's hunks, not in the card's eleven, covered by the ADR's own reading rule (L19–20: unmarked text is the original design, v2 text is as built) and therefore should-fix follow-ups, not blockers; named so the next docs-only PR in this lane takes all of them at once:

  1. §3.5 L281–285 "Local-first parity": os plugin install ./foo.osplugin "hit[s] a marketplace/install-local-style endpoint (inline artifact, register-before-persist per ADR-0016 §9.3)" — as built it is a CLI act under OS_HOME with no HTTP surface, persist at install, register at the next boot. Same class as items 9–11.
  2. §3.5 step 7 L275 "(or hot, when hotReloadable)" — retired (PluginMetadata.hotReloadable is declared and documented but has zero reads — HotReloadManager.reloadPlugin never consults it #12587), §7 says boot-only.
  3. §3.7 L397 "Supply chain. Lockfile + per-file integrity" — no lockfile ships (L142), as the dev observed.
  4. §8 References name {build,sign,publish}.ts as "the Phase 1 pipeline as built" and nothing of M1: install.ts, keygen.ts, trust/*.ts, disable.ts, enable.ts, uninstall.ts, installed-plugin-loader.ts, plugin-installation-store.ts, plugin-artifact-verdict.ts, sys-trusted-key.object.ts.
  5. sys-trusted-key.object.ts:12 and :41 docblock drift (③) — domain:server, one line each.

Summary of findings: must-fix none; should-fix three on this diff (§7 note's M2 / M3 clause; the status line's amendment list; §8 References), five pre-existing follow-ups.

Implemented-by: claude/project-thread-azb7h4
Reviewed-by: session_016WV4d1QkPVVzNz3FJqb2iS

VERDICT: PASS

…t, the M1 references, and three original-design sentences M1 made stale

From the contract review of the first two commits: the 7 note now says
rotation stays M3 and the platform / cloud source values are reserved for
the keys M2 / M3 cache from the platform chain, as the ruling body and the
sys_trusted_key docblock say; the status line lists every section this
amendment edits; 8 names the M1 files. Also corrected: 3.5 local-first
parity as built (a CLI act, no endpoint), 3.5 step 7's hot activation
(retired), and 3.7's lockfile (none ships).

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4d1j1VPnYjVUvuUMHjc
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1j1VPnYjVUvuUMHjc

Delta for the contract review: c49a117f → dd3bde29

One commit, the same one file (docs/adr/0025-plugin-package-distribution.md, +18 / −8 against c49a117f), folding in the three should-fixes of record 6512098408 and its pre-existing follow-ups 1–4 that live in this file, as the seat asked. Follow-up 5 (sys-trusted-key.object.ts docblock, domain:server) is not in this PR. Every sentence measured on f5dd05758 (no main commit since touches the ADR or the cited files).

# Where Now Evidence
S1 §7 dated note, last clause "Rotation policy stays M3; the platform / cloud values of source are reserved for the keys M2 / M3 cache from the platform chain (M2's cloud rows: root key → platform counter-signature → publisher key)." ruling 6467932167 body ("M2's chain is root key → platform counter-signature → publisher key, cached as source: 'cloud' rows in this same store"); sys-trusted-key.object.ts docblock ("source reserves platform and cloud for the keys M2 / M3 cache from that chain; M1 writes local only")
S2 Status line the amendment list names every section the amendment edits: §3.2, §3.3, §3.4, §3.5, §3.6, §3.7, §5, §7, §8 the PR's own hunks; adr-index --check OK (index cell unchanged)
S3 / F4 §8 References four lines naming the M1 files: plugin/{install,keygen,disable,enable,uninstall}.ts + plugin/trust/{add,list,revoke}.ts; installed-plugin-loader.ts, plugin-installation-store.ts, cli/src/utils/installed-plugins-boot.ts; core/src/security/plugin-artifact-verdict.ts; platform-objects/src/system/sys-trusted-key.object.ts every path listed exists on f5dd05758 (ls, all thirteen files)
F1 §3.5 "Local-first parity" the design paragraph kept; a v2 sentence: no endpoint and no Studio upload; os plugin install is a CLI act at the host that persists at install (under OS_HOME) and registers the plugin at the next boot readTarGz( production callers are install.ts, publish.ts, utils/osplugin.ts, core/security/plugin-artifact-archive.ts, installed-plugin-loader.ts — no route or handler reads an .osplugin; the console's install-local call (PackagesPage.tsx:1493) posts a manifest, not an artifact; trust/add.ts:21 "Operator-only: there is no HTTP surface"
F2 §3.5 step 7 "On next boot (v2: boot only, hotReloadable retired)" §7 Q8 answer (unchanged); installed-plugins-boot.ts header: called once, before the kernel bootstraps
F3 §3.7 Supply chain "Lockfile" dropped from the design list; a v2 sentence: no lockfile ships (bundled only, §3.3), install runs no package manager at all, integrity is re-verified at install and at every boot (M1), the scans are M3 (§3.4) §3.1 tree L142 (not shipped); install.ts:339 verifyIntegrity; installed-plugin-loader.ts check 4 (byte-equal tree); §3.4 "Not built (M3)"

Re-run on dd3bde29: dispatch-gates --commands derives the same 21 families as before (diffed); all 21 exit 0; --ran "21 derived famil(ies) accounted for — 21 run, 0 NOT-MEASURED"; adr-index --check OK; check-commit-card-trailers --range c49a117f..HEAD clean. Changed lines against the merge base now 98 (+60 / −38), under 3000. CI on the new head is running at the time of this comment.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract-review-claim: session_016WV4d1QkPVVzNz3FJqb2iS · head dd3bde2 · 2026-10-30T00:56Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: dd3bde2965ebb6143ce769fdfa3d2255a3340179
Local-runs: none
Scope: docs/adr/0025-plugin-package-distribution.md + packages/cli/src/commands/plugin/install.ts, packages/cli/src/commands/plugin/publish.ts, packages/cli/src/commands/plugin/keygen.ts, packages/cli/src/commands/plugin/trust/{add,list,revoke}.ts, packages/cli/src/commands/plugin/{disable,enable,uninstall}.ts, packages/cli/src/utils/osplugin.ts, packages/cli/src/utils/installed-plugins-boot.ts, packages/core/src/plugin-loader.ts, packages/core/src/security/plugin-artifact-signature.ts, packages/core/src/security/plugin-artifact-integrity.ts, packages/core/src/security/plugin-artifact-archive.ts, packages/core/src/security/plugin-artifact-verdict.ts, packages/runtime/src/installed-plugin-loader.ts, packages/runtime/src/plugin-installation-store.ts, packages/spec/src/kernel/manifest.zod.ts, packages/platform-objects/src/system/sys-trusted-key.object.ts, docs/adr/README.md — read on main at f5dd05758 (the PR's parent; no main commit since touches the ADR or any cited file), plus a tree-wide read of packages/rest/**, packages/services/**, packages/plugins/** and ui/** for any .osplugin surface.

Delta over record 6512098408 (PASS on c49a117f). One commit dd3bde29, the same one file, +18 / −8 over the reviewed head (the whole PR is now +60 / −38, 98 changed lines, one file). It is meant to carry that record's three should-fixes (S1 §7 note, S2 status-line amendment list, S3 §8 References) and its pre-existing follow-ups 1–4 (F1 §3.5 "Local-first parity", F2 §3.5 step 7, F3 §3.7 "Supply chain", F4 = S3); follow-up 5 (sys-trusted-key.object.ts docblock, domain:server) stays out, rightly — it is code in another lane. Inputs: relay 6512219596 on the PR (the dev's evidence table), the delta diff c49a117f..dd3bde29, the new head's full text, the check-runs on dd3bde29. Everything judged on the tree; the six items below are the diff's six hunks and the diff holds nothing else. Everything 6512098408 judged on c49a117f stands unchanged: the eleven earlier edits are byte-identical on this head and are not re-judged here.

Tier. Unchanged: Tier H (docs/adr/**), draft, no auto-merge, no requested reviewer, no assignee (the seat's relay act, as before); Governed Surface Queue Guard success on this head; 98 changed lines, under 3000.

Check-runs at this reading. 38: 15 success, 16 skipped, 0 failed, 7 still running — Test Core (1/8), Type Check · workspace, Type Check · consumer gates, Type Check · debt ledger, Lint · CI, release & engine gates, Lint · docs & code guards (the lane carrying check:adr-links and check:doc-authoring), Lint · repo & tooling gates (the lane carrying check:adr-index and check:adr-anchors). The aggregates Lint & Repo Gates, TypeScript Type Check and Test Core have not reported yet, and Check Changeset shows only its filter-skipped twin so far (on c49a117f the gate run itself reported success under skip-changeset, and nothing changeset-relevant moved). Green now: Governed Surface Queue Guard, Test UI, Check Documentation Links, Check PR Size, filter, Lint · ESLint, Lint · PM dispatch-gates, the three Lint · scoped lanes, Type Check · source gates; Build Core and the UI lanes skipped by the path filter. The seven running runs and the three aggregates are gate verdicts this record does not hold: the seat re-reads them green before asking the maintainer's approval.

① Derived judgments

One Markdown file under docs/adr/; no schema, accept set, export, generated artifact, gate or register row moves. None derived — right (unchanged).

② Semver level

Unchanged and right: Clause-②: no, Metadata-protocol: none, no changeset, skip-changeset set; the diff publishes nothing.

③ Boundary flags

The relay carries no open question and declares no deviation. Judged:

  • Follow-up 5 left out — right: a code docblock in packages/platform-objects/**, the server lane's one-liner, not this card's file surface (claim 6511498060 names the ADR alone).
  • Scope of the delta — six hunks, each one of the items the prior record named, nothing added beyond them; the claim's file surface (the one ADR) still covers every line.
  • Status-line amendment list now names nine sections: §3.2, §3.3, §3.4, §3.5, §3.6, §3.7, §5, §7, §8. Checked against the whole PR's hunks on f5dd05758..dd3bde29: the status line itself plus hunks in exactly those nine sections. Complete. docs/adr/README.md's index cell is still cut before the first changed character (check:adr-index lane running; the cell text is unchanged by inspection).
  • Changed lines 98 — under the 3000 human-merge threshold; one file.

④ Design judgment

Each new sentence against the code it cites, and against the rest of the ADR on this head:

  • S1 — §7 note, last clause. "Rotation policy stays M3; the platform / cloud values of source are reserved for the keys M2 / M3 cache from the platform chain (M2's cloud rows: root key → platform counter-signature → publisher key)." — ruling 6467932167 body verbatim in substance ("M2's chain is root key → platform counter-signature → publisher key, cached as source: 'cloud' rows in this same store"); sys-trusted-key.object.ts:26–28 ("source reserves platform and cloud for the keys M2 / M3 cache from that chain; M1 writes local only"); the source select holds the three values with local the default. Now coherent with the ADR's own §3.5 M2 bullet (the download route serves "publisher + platform signatures") and with §4 Q8 (rotation M3). Holds; the prior should-fix is closed.
  • S2 — status line. Judged under ③. Holds; closed.
  • S3 / F4 — §8 References, four new lines. All thirteen paths exist on f5dd05758 (install, keygen, disable, enable, uninstall, trust/{add,list,revoke}, installed-plugin-loader, plugin-installation-store, cli/src/utils/installed-plugins-boot, core/src/security/plugin-artifact-verdict, platform-objects/src/system/sys-trusted-key.object). Each description holds against the file's own header: installed-plugins-boot.ts is "os serve's half of the boot-time loader" and kernel.uses what passed (:131); plugin-artifact-verdict.ts is the WeakMap verdict plugin-loader.ts:544 reads before accepting a signature; sys_trusted_key holds public keys only. Code spans in the same form the existing reference lines use, no link syntax, so check:adr-links has nothing new to resolve. Holds; closed.
  • F1 — §3.5 "Local-first parity", the appended v2 sentence. "no endpoint and no Studio upload; os plugin install is a CLI act at the host that persists at install (under OS_HOME) and registers the plugin at the next boot." — tried to break it: the production callers of readTarGz( on f5dd05758 are install.ts:277, publish.ts:110, utils/osplugin.ts:142 and installed-plugin-loader.ts:353 (plus its definition in plugin-artifact-archive.ts:97) — no route handler; the string .osplugin occurs nowhere in packages/rest/**, packages/services/**, packages/plugins/** or any non-test file under ui/**, and the console's install-local surface (marketplaceApi.ts, MarketplacePackagePage.tsx) carries a manifest, not an artifact; trust/add.ts:21 "there is no HTTP surface"; install.ts header "Writes no database row in any mode", materializes under OS_HOME (plugin-installation-store.ts:8) and records; installed-plugins-boot.ts header "Called once, after the config's plugins are registered and before the kernel bootstraps". The design sentence is kept and the as-built sentence is v2-marked, the ADR's own convention (L19–20). Holds; closed. §3.11 L521–525 ("the os plugin install / control-plane path … performed by an operator with the permission-consent step") is the pre-existing audience text and is not contradicted: the local path's consent is the declared set recorded as granted (§3.5 v2 "there is no partial grant"), the control-plane half has the console step.
  • F2 — §3.5 step 7. "On next boot (v2: boot only, hotReloadable retired)" — §7 Q8 answer unchanged; installed-plugins-boot.ts header; #12587 retirement already recorded at §3.7 L393 and §7 L637. The step's closing "that JSON is hot-registered exactly like a pure-element package" is the engine-registration sense of the JSON flow (§0), at that same boot — not hot reload; no contradiction. Holds; closed.
  • F3 — §3.7 "Supply chain". "Per-file integrity; … v2: no lockfile ships (bundled only, §3.3), so install runs no package manager at all; integrity is re-verified at install and at every boot (M1); the scans are M3 (§3.4)." — "no lockfile ships" holds (§3.1 L142; build.ts packs dist/index.mjs, assets/, the manifest and the SIGNATURE placeholder only); "install runs no package manager" holds (install.ts, §3.5 step 5 v2); "the scans are M3" holds (§3.4 "Not built (M3)"); "integrity is re-verified at install" holds (install.ts:339 verifyIntegrity, refusing mismatch / missing / undeclared). Should-fix (the one finding of this delta): "and at every boot" names a mechanism that does not run at boot. verifyIntegrity's production callers are install.ts:339 and publish.ts:141 only, and the word integrity does not occur in installed-plugin-loader.ts: at boot, check 4 (:350–389) holds the install directory byte-equal to the kept artifact — whose signature check 3 verified over its raw bytes — with no file beside the artifact's own, which is a stronger guarantee than the per-file map and is what the ✅ line already names correctly ("artifact sha, signature, byte-equal tree"). The dev's own evidence cell cites check 4, so the wording lags the evidence. One clause: "integrity is re-verified at install, and at every boot the install directory is held byte-equal to the signed artifact (M1)". Not a must-fix: the guarantee the sentence promises is delivered, by a stronger check, and no reader is sent to a check that refuses less than the text says; a respin or the next docs-only PR in this lane.

No new sentence contradicts another on this head: the parity v2 sentence agrees with §3.5 step 6 (local store), step 7 (next boot), the ✅ line and §3.11; the supply-chain v2 sentence agrees with §3.3, §3.5 step 5 v2 and §3.4; the §7 note agrees with §3.5 M2, §4 Q8 and the trusted-key object; the status line names every amended section. The prior record's five-phrase grep still answers 0; hotReloadable now occurs only as retired (L275, L393, L637) and "lockfile" only as not shipping (L401). The eleven earlier edits are byte-identical to the PASS head.

Summary of findings: must-fix none; should-fix one (F3's "at every boot" clause); the three prior should-fixes and follow-ups 1–4 are closed on this head; follow-up 5 stays with domain:server.

Implemented-by: claude/project-thread-azb7h4
Reviewed-by: session_016WV4d1QkPVVzNz3FJqb2iS

VERDICT: PASS

…boot the tree is held byte-equal to the signed artifact

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4d1j1VPnYjVUvuUMHjc
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract-review-claim: session_016WV4d1QkPVVzNz3FJqb2iS · head f26a4b3 · 2026-10-30T01:10Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: f26a4b361302b2a0a053cf28025d5e8a055d4e53
Local-runs: none
Scope: docs/adr/0025-plugin-package-distribution.md + packages/cli/src/commands/plugin/install.ts, packages/runtime/src/installed-plugin-loader.ts, packages/core/src/security/plugin-artifact-integrity.ts, packages/cli/src/commands/plugin/publish.ts, packages/cli/src/commands/plugin/build.ts — read on f5dd05758 (the PR's parent) and re-read on main at fec60e00b, which is seventeen commits past the parent and, through #27791, changed install.ts, installed-plugin-loader.ts and build.ts (the ADR itself and every other cited file are untouched on main).

Delta over records 6512098408 (PASS on c49a117f) and the delta record on dd3bde29. One commit f26a4b36 on top of dd3bde29, the same one file, +3 / −2, one hunk in §3.7 "Supply chain" and nothing else (git diff dd3bde29..f26a4b36 holds that hunk alone; the whole PR is now +61 / −38, 99 changed lines, one file). It applies the delta record's one should-fix. Inputs: the seat's Contract-review-claim 6512429742 naming this head and this reviewing session; the delta diff; the head's full text; the check-runs on f26a4b36; the compare of the parent against main. Judged on the tree. Everything the two earlier records judged stands: the seventeen earlier edits are byte-identical on this head.

Tier. Unchanged: Tier H (docs/adr/**), draft, no auto-merge, no requested reviewer, no assignee (the seat's relay act); Governed Surface Queue Guard success on this head; 99 changed lines, under 3000; skip-changeset set.

Check-runs at this reading. 38: 13 success, 16 skipped, 0 failed, 9 still running — Test Core (1/8), Type Check · workspace, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Lint · ESLint, Lint · CI, release & engine gates, Lint · docs & code guards (the lane carrying check:adr-links and check:doc-authoring), Lint · repo & tooling gates (the lane carrying check:adr-index and check:adr-anchors). The aggregates Lint & Repo Gates, TypeScript Type Check and Test Core have not reported, and Check Changeset shows only its filter-skipped twin so far. Green now: Governed Surface Queue Guard, Test UI, Check Documentation Links, Check PR Size, filter, Auto Label, Dogfood Regression Gate, Plan Test Core shards, PR-body guards, Lint · PM dispatch-gates, the three Lint · scoped lanes; Build Core and the UI lanes skipped by the path filter. Those nine runs and the three aggregates are gate verdicts this record does not hold: the seat re-reads them green before asking the maintainer's approval.

① Derived judgments

One Markdown file under docs/adr/; no schema, accept set, export, generated artifact, gate or register row moves. None derived — right (unchanged).

② Semver level

Unchanged and right: Clause-②: no, Metadata-protocol: none, no changeset, skip-changeset; the diff publishes nothing.

③ Boundary flags

  • The delta is the one clause asked for and nothing more — one hunk, §3.7, three lines in and two out; no other line of the file moved between dd3bde29 and f26a4b36.
  • main moved under the PR. Seventeen commits since the parent; fix(cli)!: os plugin install and the boot loader parse the compiled manifest through ManifestSchema #27791 ("os plugin install and the boot loader parse the compiled manifest through ManifestSchema", the slice-3 review's follow-up ①.4) rewrote the manifest read in install.ts and installed-plugin-loader.ts, and build.ts gained the importer-chain diagnostic (that review's follow-up 5). None touches the ADR, so the PR still applies cleanly; every ADR sentence that names those files was re-read against fec60e00b (④) and none became false. Not a deviation; recorded so the seat knows the reading tree.
  • The dev's report line "install.ts:339 is the one caller" of verifyIntegrity: on f5dd05758 the production callers are install.ts:339 and publish.ts:141 (the publish-side pre-check), and on main the install call sits at :337. The ADR clause claims only "at install", which is true; the report line is imprecise about publish.ts, not about the tree. Observation, no finding.
  • Claim 6512429742 names this exact head and session_016WV4d1QkPVVzNz3FJqb2iS; the PR head, branch claude/project-thread-azb7h4, and the claim agree.

④ Design judgment

The one new sentence, against the code it cites, on both trees:

  • §3.7 "Supply chain", the v2 clause. "integrity is re-verified at install, and at every boot the install directory is held byte-equal to the signed artifact (M1)" —
    • at install: install.ts calls verifyIntegrity(files, …, { exempt: [manifest, SIGNATURE] }) after the archive is read and refuses integrity_mismatch (mismatch, missing, undeclared) — :339 on f5dd05758, :337 on main, where the map's shape is now ManifestSchema's before the check runs. Holds on both.
    • at every boot: installed-plugin-loader.ts never reads the integrity map (the word does not occur in the file on either tree; verifyIntegrity's production callers are install.ts and publish.ts only); check 4 reads the kept artifact back (readTarGz, :353 / :357), compares every file in the install directory byte-for-byte to its entry (sameBytes, :383 / :384), refuses any file the artifact does not hold and any entry missing, and names the refusal tree_changed — "its install directory is not the signed artifact any more" (:388 / :389); check 3 verified the signature over those raw bytes first. "Held byte-equal to the signed artifact" is exactly that. Holds on both. An install admitted under --trust-unsigned is held byte-equal to its kept, unsigned artifact the same way (check 4 runs regardless); "signed" names the security model's normal case, and §3.5 already records the override as the loud exception — no finding.
    • The clause now agrees with the ✅ line's "re-verifies each install (artifact sha, signature, byte-equal tree)" and claims no check that does not run. The delta record's should-fix is closed.
  • The rest of the ADR against main at fec60e00b, since the cited code moved: the ✅ line's install clauses (signature over the raw bytes before readTarGz, :259 then :282; integrity re-verified; materialize; record) and boot clauses (artifact sha, signature, byte-equal tree, tier dispatch :393, kernel.use) still hold — fix(cli)!: os plugin install and the boot loader parse the compiled manifest through ManifestSchema #27791 adds a ManifestSchema parse at both doors (manifest_invalid), a stronger check the ADR does not contradict; §3.3's "refuses one before writing anything" still holds (write: false :315, findNativeAddons :347, computeIntegrity :360, the only writes :375–376); §3.4 step 2, §3.6, §7 cite files main did not touch. No sentence of the PR became false under the moved tree.

No new sentence contradicts another: §3.7's clause, the ✅ line and the loader header say the same thing in the same order. The seventeen earlier edits are byte-identical to the heads the two prior records passed.

Summary of findings: must-fix none; should-fix none; the one open should-fix is closed; follow-up 5 (the sys-trusted-key.object.ts docblock) stays with domain:server.

Implemented-by: claude/project-thread-azb7h4
Reviewed-by: session_016WV4d1QkPVVzNz3FJqb2iS

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

维护者速读

  • 改了什么:ADR-0025 v2 按 M1 实际落地的样子改写,只动一个文件(+61/−38)。状态行写明 M1 本地 T0 安装闭环已落地(os plugin install、受信公钥库、启动期加载器与 tier 分派点、disable / enable / uninstall),云端样例验收 plugin install acceptance e2e on cloud plugins/connector-stripe: build, sign, install, boot, one tool, disable, tamper cases (#27123 item 6) #27570 仍未完成。§3.3 写明 manifest-deps 已退役(schema 按名拒绝),构建会拒原生 .node 插件。§3.5 第 5、7 步与 M1 条目照树改写。§3.6 写明启动期按 tier 分派:node 进程内,sandbox / worker 按名拒绝。§3.7 写明安装时复验 integrity,每次启动时要求安装目录与签名产物逐字节一致。§7 补 sys_trusted_key 的裁决注记,§8 补参考文件。
  • 为什么改:ADR-0025 是插件分发的治理文本,原文仍说 manifest-deps 有效、安装步骤 4–7 不存在,人和 AI 照它读会得出与代码相反的结论。
  • 风险与回滚:只改 ADR 文字,不改行为;revert 即回滚。
  • 先看:状态行与 §3.5 的 M1 条目(✅ landed 2026-10-29),以及 §3.7 Supply chain 末句。
  • 两分钟验证:grep -n "manifest-deps" docs/adr/0025-plugin-package-distribution.md,剩下的每一处都应写成 RETIRED 或退役语境。
  • 需要你做的:受管面 Tier H,请批准本 PR(契约复核 PASS 6512486769,Head-sha: f26a4b361302b2a0a053cf28025d5e8a055d4e53)。

席位意见:ACCEPT。三轮契约复核:首轮 PASS(3 条 should-fix、5 条既有 follow-up),第二轮差量 PASS(1 条 should-fix:§3.7「每次启动复验 integrity」不实),第三轮差量 PASS(该句改为「安装时复验,启动时逐字节一致」),CI 全绿。

席位核对

@os-zhuang
os-zhuang marked this pull request as ready for review October 30, 2026 01:26
@os-zhuang
os-zhuang enabled auto-merge October 30, 2026 01:26
@os-zhuang
os-zhuang added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 30f8fdd Oct 30, 2026
50 checks passed
@os-zhuang
os-zhuang deleted the claude/project-thread-azb7h4 branch October 30, 2026 01:53
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/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(adr): ADR-0025 v2 still describes manifest-deps and the pre-M1 install gap; the #27123 Tier H docs follow-up

2 participants