Skip to content

feat(runtime): PATCH /api/v1/packages/:id edits a package's manifest dependencies - #24703

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-24670-package-dependencies-patch
Oct 20, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-24670-package-dependencies-patch

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #24670
Clause-②: yes (widening)

What changed

PATCH /api/v1/packages/:id now accepts the manifest's dependencies row beside name, description and version, flat or under the manifest wrapper.

  • The door (packages/runtime/src/domains/packages.ts, the PATCH /packages/:id arm only). The row is judged by ManifestSchema.shape.dependencies from @objectstack/spec, the row POST /packages parses at create. Nothing is restated. A malformed row is refused 400 VALIDATION_ERROR, the envelope the create door answers for the same row, before the protocol or the registry is reached. So nothing is written, including a valid key sent beside it. The "nothing to update" 400 now names dependencies among the accepted keys.
  • The registry (packages/objectql/src/registry.ts, SchemaRegistry.updatePackageManifest only). It copies dependencies when present. The row replaces the stored one whole, never a deep merge, and the registry keeps its own copy. An entry the row leaves out is removed, and {} clears the declaration. Replacing the object, rather than editing it in place, also keeps the protocol's shallow pre-patch snapshot able to put the prior row back when the durable write fails.
  • The protocol (packages/metadata-protocol/src/protocol.ts, updatePackage only). The patch type gains dependencies. Persistence needed no change: updatePackage already re-persists the whole merged manifest through persistPackageManifest.

The objectui half (Studio's edit dialog sends only the three keys) is not in this PR. Triage 6279169921 routes it to objectui once this door accepts the row.

Mechanism assumptions, measured

  1. The widened registry merge carries dependencies into sys_packages. Holds on both branches. On the protocol branch, pin (a) reads the sys_packages row through the real PackageServicePlugin and re-reads it after a restart. On the in-memory fallback, the door test reads the registry and GET /packages/:id.
  2. The closure reader reads manifest.dependencies live. Holds. The one runtime reader is resolveWritePackageScope (protocol.ts). It walks registry.getPackage(id).manifest.dependencies on every write and caches nothing. git grep found no other runtime reader of manifest.dependencies in metadata-protocol, objectql, runtime, services/* or lint. Pin (d) shows the next save sees the edit with nothing retired.
  3. A malformed row takes the create door's envelope. Holds. POST /packages with dependencies: { "com.acme.core": 1 } answers 400 VALIDATION_ERROR. The PATCH answers the same status and code, and a parity test pins this.
  4. The new key follows the arm's flat or wrapped reading. Holds. Both forms are pinned, and the refusal locates the key as dependencies.KEY or manifest.dependencies.KEY, following the form the caller wrote.

Removing a dependency: readings for the seat

The PATCH applies the row as given, and no in-use check was built. Measured over the integration harness below, which runs the real ObjectQL, SqlDriver (better-sqlite3), PackageServicePlugin, protocol on the default authoring channel and HttpDispatcher. Package P declares D. A list view stored in P binds to D's object. Then PATCH /packages/P sends { "dependencies": {} }, which answers 200, and the steps below were measured with a one-off probe that is not committed:

step answer
read, protocol.getMetaItem resolves; _diagnostics: { valid: true }
read, GET /meta/view/NAME (dispatcher) 200, no _diagnostics on the item
registry after removal still serves the view
re-save of the unchanged body, protocol.saveMetaItem 422 INVALID_METADATA, rule list-view-object-outside-closure; the stored row is unchanged
re-save, PUT /meta/view/NAME?package=P (dispatcher) 422 INVALID_METADATA, rule list-view-object-outside-closure
re-hydrate in process, loadMetaFromDb() { loaded: 2, errors: 0, invalid: 0, storeUnavailable: false }; the view stays registered
restart (same database), package row dependencies: {} served
restart, loadMetaFromDb() { loaded: 2, errors: 0, invalid: 0, storeUnavailable: false }; the view is registered
restart, read GET /meta/view/NAME 200
restart, re-save 422 INVALID_METADATA, list-view-object-outside-closure

So an item stored before the removal keeps loading and serving, and neither the boot count nor the read badge flags it. Its next save is refused with the closure verdict, which names the remedy (declare the dependency again).

Tests

All runs are on head 0fcd8e42c unless noted. @objectstack/objectql and @objectstack/metadata-protocol resolve to dist/ in the runtime suites, so both were rebuilt before every reading.

  • Red before the fix (commit 7a83ce21f, pre-fix build): 13 of 16 runtime cases and both registry cases failed. The (d) refusal step already passed (422 INVALID_METADATA, list-view-object-outside-closure) and the case failed at the PATCH: 400 "Body { name?, description?, version? } — nothing to update". A valid name sent beside a malformed row answered 200 and was written.
  • New pins, green:
    • packages/runtime/src/domains/packages-patch-dependencies.test.ts: real HttpDispatcher over a real SchemaRegistry. Covers the row persisted flat and wrapped, whole-row replace, four malformed rows refused with nothing written, refusal before the protocol is called, parity with POST /packages, and (c) the three existing keys as before.
    • packages/runtime/src/package-dependencies-patch.integration.test.ts: (a) persisted, served, stored in sys_packages and served after a restart; (b) malformed refused with neither store moving, and a sys_packages-refused edit (a trigger) answers 500 with the prior row back in the registry, GET and the store; (d) the remedy end to end.
    • packages/objectql/src/registry.test.ts: two [#24670] cases.
    • Result: Tests 17 passed (17) and Tests 103 passed (103).
  • Package suites:
    • @objectstack/objectql (--project local): Test Files 448 passed (448), Tests 8449 passed (8449).
    • @objectstack/metadata-protocol: Test Files 249 passed | 3 skipped (252), Tests 20781 passed | 19 skipped (20800).
    • @objectstack/runtime (--project local): Test Files 427 passed (427), Tests 6695 passed | 19 skipped (6714).
    • Each VERDICT command-exit 0.
  • Typecheck: pnpm --filter on the three packages exits 0, including each package's check:test-typecheck.
  • Ablation (commit c88492672). Through scripts/ablation-replace.mjs, the line if (patch.dependencies !== undefined) manifest.dependencies = { ...patch.dependencies }; was deleted: anchor 1 to 0, blob 0d0948aec118 to d2dd6f3e9d62.
    • objectql was rebuilt, and ablation-dist-preflight.mjs @objectstack/objectql "manifest.dependencies = {" --absent found the marker absent from all 14 built files. Before the mutation it was present in 4 (core.js, core.mjs, index.js, index.mjs).
    • Red under the ablation: (a), (d), the rollback case, the three fallback-persistence cases and both registry cases. The door's refusal cases stayed green, as expected: they do not reach the registry.
    • Restore: blob back to 0d0948aec118, git diff HEAD empty. After a rebuild, the preflight found the marker in 4 files, the tree was clean, and the 17 + 2 cases were green.

Gates

  • node scripts/pm/dispatch-gates.mjs --commands at 0fcd8e42c derived 72 commands. --ran reconciliation: 72 accounted, 71 exit 0, 1 NOT MEASURED.
  • NOT MEASURED: pnpm check:dual-build-cjs-loads exits 3 with PREREQUISITE NOT MET. It reads the whole workspace's dist/, and only this card's closure was built. CI's Lint & Repo Gates runs it.
  • check-engine-split-ratio --days 90 and check-plugin-teardown-shape --self-test refused on the shallow clone. After deepening (git fetch --shallow-since=2026-07-14), both exit 0.
  • The roster families whose roster is in a touched directory (check-changeset-fixed, check:authz-resolver, check:error-code-casing, check:route-ledger-census) exit 0.
  • pnpm lint (eslint . --no-inline-config) exits 0 at 0fcd8e42c.

Export measurement (sets the bumps)

The dist .d.ts was compared before and after.

  • @objectstack/objectql: index.d.ts and core.d.ts are identical, apart from the chunk hash. One signature changed: SchemaRegistry.updatePackageManifest's patch gains dependencies?: Record(string, string).
  • @objectstack/metadata-protocol: one signature changed: updatePackage's request.patch gains the same optional key.

No export was added, removed or renamed. Both are accept-set widenings, so the changeset takes minor on all three packages (runtime, objectql, metadata-protocol).

Acceptance notes


Generated by Claude Code

…d before the fix)

Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6
Co-authored-by: Claude <noreply@anthropic.com>
… row

The door judges the row by ManifestSchema's dependencies row and refuses a
malformed one 400 before any write; SchemaRegistry.updatePackageManifest
replaces the row whole and the protocol's updatePackage persists it.

Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6
Co-authored-by: Claude <noreply@anthropic.com>
…r the dependencies edit

Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/metadata-protocol, @objectstack/objectql, @objectstack/runtime, touching 11 documentable anchor(s).

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

  • content/docs/api/client-sdk.mdx (via packages.uninstall (sdk, the route ledger binds it to DELETE /packages/:id))
  • content/docs/api/environment-routing.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/api/metadata-api.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/concepts/metadata-lifecycle.mdx (via ObjectStackProtocolImplementation (symbol, a top-level class), SchemaRegistry (symbol, a top-level class))
  • content/docs/data-modeling/formulas.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/deployment/environment-variables.mdx (via SchemaRegistry (symbol, a top-level class))
  • content/docs/deployment/publish-and-preview.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/kernel/contracts/metadata-service.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/kernel/services-checklist.mdx (via SchemaRegistry (symbol, a top-level class))
  • content/docs/permissions/permission-sets.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/permissions/system-context.mdx (via handlePackagesRequest (symbol, a top-level function), /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/plugins/adding-a-metadata-type.mdx (via SchemaRegistry (symbol, a top-level class))
  • content/docs/protocol/kernel/error-handling.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/protocol/kernel/lifecycle.mdx (via manifest.dependencies (literal, a string literal in handlePackagesRequest))
  • content/docs/protocol/kernel/plugin-spec.mdx (via manifest.dependencies (literal, a string literal in handlePackagesRequest))

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

  • content/docs/releases/v15.mdx (via /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/releases/v16.mdx (via ObjectStackProtocolImplementation (symbol, a top-level class))
  • content/docs/releases/v17/17-0.mdx (via ObjectStackProtocolImplementation (symbol, a top-level class), /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/releases/v17/17-1.mdx (via manifest.dependencies (literal, a string literal in handlePackagesRequest))
  • content/docs/releases/v17/17-4.mdx (via SchemaRegistry (symbol, a top-level class), /packages/:id (route, a path literal in a comment in ObjectStackProtocolImplementation; a path literal in a comment in SchemaRegistry))
  • content/docs/releases/v17/17-5.mdx (via packages.get (sdk, the route ledger binds it to GET /packages/:id))

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 — 39 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 9b2953d62c50a851604afbe91e3a48c90d72645f → packageMentionDocs.

Which tree this was computed on

This run read content/docs from b8441ec96c9d3a46ce7793c9960aeddac0ead28f — the merge of head 7a8557cff1d62fac022377bcdf91cb7950d1ba5f into base 9b2953d62c50a851604afbe91e3a48c90d72645f, 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 b8441ec96c9d3a46ce7793c9960aeddac0ead28f && git checkout b8441ec96c9d3a46ce7793c9960aeddac0ead28f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9b2953d62c50a851604afbe91e3a48c90d72645f 7a8557cff1d62fac022377bcdf91cb7950d1ba5f && git checkout -B drift-repro 9b2953d62c50a851604afbe91e3a48c90d72645f && git merge --no-ff 7a8557cff1d62fac022377bcdf91cb7950d1ba5f

node scripts/docs-audit/affected-docs.mjs --json 9b2953d62c50a851604afbe91e3a48c90d72645f

⚠️ 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 9b2953d62c50a851604afbe91e3a48c90d72645f → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 0fcd8e42c267862c8a10f8f7a89d40b5a4999ed1
Local-runs: none

The face is the Clause-②: yes declaration alone. check-governed-merges.mjs --pr 24703 reads 0 of 7 paths on the register, and no packages/spec/src/** path is in the diff. The review read the diff, card #24670 with triage's grade 6279169921, and origin/main d1173825b.

① Derived judgments

  • Accept set of PATCH /api/v1/packages/:id: widened by one key, correctly.
    • dependencies is accepted flat or under manifest, and judged by ManifestSchema.shape.dependencies by reference. It is the row POST /packages parses at create, so nothing is restated.
    • A malformed row is refused 400 VALIDATION_ERROR before the protocol or the registry is reached. A valid key sent beside it is not written either.
    • Pins assert { status, code }, parity with the create door, and stores unmoved, on both branches.
    • The three existing keys keep their answers, including the empty-name refusal, the non-SemVer refusal and the empty body, which now names dependencies. That is triage's pin (c).
  • Published signatures: widened, nothing removed. SchemaRegistry.updatePackageManifest (@objectstack/objectql) and ObjectStackProtocolImplementation.updatePackage (@objectstack/metadata-protocol) each gain one optional dependencies key. No export is added, removed or renamed.
  • Write semantics.
  • Removal, decided on the readings in the PR body: applied as given. An item stored before the removal keeps loading and serving through reads, loadMetaFromDb and a restart. Its next save is refused 422 INVALID_METADATA with the closure verdict, which names the remedy. This matches the standing rule that the closure is judged at the save door, not at read or boot. No data is lost silently, and the next write is a loud refusal.
  • The IObjectQLEngine registry contract still declares the three-key patch. That is EngineSchemaRegistryView.updatePackageManifest, packages/spec/src/contracts/objectql-engine.ts:131. It under-declares the implementation and does not contradict it: the door compiles through it. packages/spec is the spec seat's, and the line is noted for it.

② Semver level

minor on @objectstack/runtime, @objectstack/objectql and @objectstack/metadata-protocol, with Clause-②: yes (widening) in the changeset and the PR body. A widening takes at least minor, so the declaration and the level agree.

③ Boundary flags

Implemented-by: claude/issue-24670-package-dependencies-patch
Reviewed-by: session_01LmjU2x1faLZ39DVTFyVca6

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT

domain:cli seat 2 (#22648) · os-justin · session session_01LmjU2x1faLZ39DVTFyVca6 · 2026-10-20T00:44Z · head 0fcd8e42c267862c8a10f8f7a89d40b5a4999ed1 · claim 6279409111 → report os-dev-report on #24670 → review of record 6280612601 (TIER_DEFAULT, PASS).

Check Reading
Shape Draft, base main. First line Fixes #24670; Clause-②: yes (widening) is line-initial in the body and the changeset. Assignee os-justin = the card's. The closing keyword names #24670 only (the body names #24705 nowhere).
Surface 7 files, all inside the claim plus 6279452248 on #6367: the PATCH arm only in packages.ts, updatePackageManifest only in registry.ts, and updatePackage only in protocol.ts, plus tests and one changeset. No content/docs/releases/, no packages/spec/**. check-governed-merges.mjs --pr 24703: NOT governed, 662 changed lines, ≤ 3000.
Premises Read on origin/main d1173825b. The closure reader resolveWritePackageScope (protocol.ts:7798) is per write. packages/rest serves only GET and DELETE on /packages/:id, so the dispatcher arm is the one PATCH owner.
Refusals Spot-checked in the diff: each malformed-row case asserts { status: 400, code: 'VALIDATION_ERROR' } with stores unmoved, and the create-door parity case asserts the same pair. (d) asserts { code: 'INVALID_METADATA', status: 422 } before the PATCH, and admission after it.
Changeset Read line by line against the diff. "row replaces the stored one whole", "{} clears the declaration", "the prior row is put back and the door answers the failure", "no in-use check is made", "keeps loading and serving after a restart; its next save is refused" and "no export is added, removed or renamed" each match a hunk or a pinned case. minor ×3 agrees with Clause-②: yes (widening).
Gates Check-runs on this head (38, latest per name), read at this act: 24 success, 6 skipped, and 8 in_progress (Test Core 1–6/6, Type Check · consumer gates, Type Check · workspace). Lint · ESLint and every Lint · job: success. Landing waits on all of them.

Accepted deviations:

  • The dev deepened the shared clone, which moved the shared origin/main ref.
  • check:dual-build-cjs-loads was NOT MEASURED locally. CI's Lint jobs carry it, and they are green.
  • test:repo was left to CI's Test Core.

Out-of-scope dispositions (one line each):

Landing: through the merge queue by this seat once every check on this head reads success (or an expected skip). Merge main only on a GitHub-reported conflict, a main-caused red or a queue removal.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Landing hold · domain:cli seat 2 · session session_01LmjU2x1faLZ39DVTFyVca6 · 2026-10-20T01:09Z. The ACCEPT 6280623704 and the review of record 6280612601 stand. This PR stays in draft and out of the queue until both of these clear:

  1. Main-red hourly full run: red on main (CI) #24700. The hourly full run is red in this lane: wall-environment-metadata-refusal.dogfood.test.ts, a fixture made stale by PR fix(lint)!: the save door refuses a list view written into a package and bound outside its closure #24630. AGENTS.md says no lane PR arms the queue while it is red. Its fix is dispatched as claim 6280921751.
  2. packages: PATCH /api/v1/packages/:id edits a read-only package's manifest (200), where disable, publish, revert, delete and install-overwrite refuse it 422 WRITABLE_PACKAGE_REQUIRED #24705 lands first. It gates this same PATCH /packages/:id arm with requireWritablePackage (ADR-0070), and triage 6280778865 orders it "with or before" this PR. Claim 6280929612. After it lands, this PR merges main, the seat reads the change-line set and the check-runs on the new head, and the ACCEPT carries forward in an addendum.

Generated by Claude Code

Resolves the PATCH /packages/:id arm conflict in packages/runtime/src/domains/packages.ts:
main's ADR-0070 read-only gate (requireWritablePackage ... 'edit') is kept exactly as main
has it, and this branch's wrapped/src/patch/dependencies handling follows it unchanged.

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

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 7a8557cff1d62fac022377bcdf91cb7950d1ba5f
Local-runs: none

This head is a merge of origin/main 9b2953d62 (PR #24719, #24705's ADR-0070 gate) into the reviewed head 0fcd8e42c, whose record is 6280612601 (TIER_DEFAULT, PASS). The face is still the Clause-②: yes declaration alone: NOT governed, and no packages/spec/src/** path in the diff.

① Derived judgments

② Semver level

Unchanged: minor on @objectstack/runtime, @objectstack/objectql and @objectstack/metadata-protocol, with Clause-②: yes (widening). The merge adds no changeset line, and #24719 carries its own.

③ Boundary flags

Implemented-by: claude/issue-24670-package-dependencies-patch
Reviewed-by: session_01LmjU2x1faLZ39DVTFyVca6

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · addendum: ACCEPT carried to 7a8557cff

domain:cli seat 2 · os-justin · session session_01LmjU2x1faLZ39DVTFyVca6 · 2026-10-20T03:31Z · new head 7a8557cff1d62fac022377bcdf91cb7950d1ba5f, after patch round 1 (report 6282650839 on #24670).


Generated by Claude Code

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/l tests tooling

Projects

None yet

2 participants