Repository navigation
plugin-spec.mdx's PLUGIN MANIFEST examples still pin @objectstack/core at ^2.0.0 (kernel-resolved surface, not the npm one #17378 repaired) — with the kernel-resolution leg unmeasured #18188
Description
Activity
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentation
on Sep 14, 2026 os-try-charles commented
on Sep 16, 2026 CollaboratorMore actionsClaim: PM loop round 5
Session:session_017ef78bLdybu3AffehKkhfk
Branch:claude/issue-18188-manifest-example-version-ranges
Worktree:objectstack-issue-18188
Domain:domain:devx
File surface:content/docs/protocol/kernel/plugin-spec.mdx(stop on breach; explain in the report) —packages/**is reachable read-only, for the kernel-resolution reading the acceptance asks for
Container & model:S,mode:subagent,model: opus— this call's--tieroncontent/docs/protocol/kernel/plugin-spec.mdxprinted "no path-derived mandate: the surface hits none of the 3 declared glob(s), derived here, not recalled", so the tier is the PM's judgment call and stays at the default.
Clause-②: no
Thread-read: 5690478248
Serial constraints cleared: none in flight — open-PR listing taken at 2026-09-16T09:19Z (the same reading as the #17472 claim in this round), each PR's file list re-read immediately before this claim; all 13 open PRs had their file lists read and zero touchplugin-spec.mdx; the npm-side predecessor PR #18186 (card #17378) is merged (076bb975de, 2026-09-14T12:55Z).⚠️ Named, not a constraint: epic #15952 (pm:epic,domain:cli, unassigned, no PR) holds the Plugin Testing section of the same file at:758-765— a different section and a different subject, so this card is not inside that subtree.⚠️ N = this session's 5th dispatch round; this is its second card. It is independent of #17472, not a fold member — the two file surfaces are disjoint.Pre-claim probe — every site the card names is still there, at these lines
Probed at 2026-09-16T09:22Z in a detached worktree at
origin/mainf04be62aa(⛔ not the shared checkout). The file is 990 lines.site line text manifest example #1 60 '@objectstack/core': '^2.0.0',manifest example #2 436 '@objectstack/core': '^2.0.0',the pin-vs-caret lesson 942 '@objectstack/core': '2.0.0', // Not '^2.0.0'Firing control
@objectstack/core= 12 hits in this file · dark control = 0, both taken from the probed file itself.
@objectstack/core's current version read frompackages/core/package.json= 17.4.0 — the card's number, confirmed.⚠️ One thing the card does not name. The same two manifest examples also carry'@objectstack/ui': '^2.0.0'at lines 71 and 462 — same shape, same page, samedependenciesmap. ⛔ I am not grading them:@objectstack/uiis not a package in this repository (nopackages/*/package.jsondeclares that name), so whether^2.0.0is wrong for it is not answerable from this checkout. The dev reports what it finds and ⛔ changes nothing there without a reading.Fences carried into the dispatch
- ⛔ The load-bearing leg is UNMEASURED and stays that way until someone measures it: does the kernel actually resolve
@objectstack/coreas a manifest dependency at plugin load? If yes → class (a); if no → an inert wrong number. ⛔ Do not infer it from the npm side — a different resolver with a different failure mode. - ⛔ The line-942 exact pin is the worked example of a lesson about pinning versus caret. Read the section before touching the number; the prose and the demonstration must still argue the same thing afterwards.
- ⛔ The suggested three-step shape in the card is a proposal, not a prescription.
PM seat
domain:devx· round 5, second card · 2026-09-16T09:23Z
Generated by Claude Code
- ⛔ The load-bearing leg is UNMEASURED and stays that way until someone measures it: does the kernel actually resolve
os-try-charles commented
on Sep 16, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 18188, "status": "done", "branch": "claude/issue-18188-manifest-example-version-ranges", "pr": "https://github.com/objectstack-ai/objectstack/pull/18415", "premise_still_valid": true, "summary": "The three sites the card names were all still present at the stated lines and are now repaired: the two PLUGIN MANIFEST `dependencies` carets at :60 and :436 move from '^2.0.0' to '^17.0.0' (matching the npm half of the same page, already at '^17.0.0' since PR #18186), and the pin-vs-caret worked example at :942 moves from '2.0.0' / comment 'Not ^2.0.0' to '17.4.0' / comment 'Not ^17.0.0', which keeps that lesson's argument (exact pin beats caret) form for form. HALF THE CARD'S FRAMING IS FALSIFIED BY THE READING IT ASKED FOR: the manifest `dependencies` surface is kernel-CONSUMED but not kernel-RESOLVED. Both production consumers take Object.keys(...) only, so the version range value is never parsed and a wrong one fails nothing at load -- an inert wrong number, not class (a). Because the page's prose implied an enforcement that does not happen, the PR also adds one Callout under 'Version Constraints' naming the two real consumers and the dead SemanticVersionManager/DependencyResolver pair, and re-anchors the 'Pin Core Dependencies' reason on the installer and on package.json (which npm does resolve) instead of on a kernel check that does not exist. The @objectstack/ui sites at :71 and :462 are deliberately UNCHANGED -- see open_questions.", "tests": "KERNEL-RESOLUTION READING (the load-bearing leg), call site first: manifest.dependencies has exactly two production consumers, both Object.keys(...) only -- packages/core/src/artifact-packages.ts:282 (ids -> resolvePluginOrder as optionalDependencies) and packages/metadata-protocol/src/protocol.ts:5346 (ids walked transitively for the write-scope closure). SemanticVersionManager/DependencyResolver (packages/core/src/dependency-resolver.ts) have ZERO production importers. Instrument controls, all from the probed corpus: SUBJECT grep 'dependency-resolver.js' = 2 hits, both non-production (index.ts:126 barrel re-export, dependency-resolver.test.ts:2 its own unit test); FIRING CONTROL 'plugin-order.js' (same dir, same barrel, same export form) = 5 hits incl. 4 production importers; DARK CONTROL 'dependency-resolver-NOSUCH.js' = 0. The instrument discriminates. EXECUTED LEG against built packages/core/dist/index.js calling resolveArtifactPackageOrder :: exit 0 -- S1 '@objectstack/core':'^2.0.0' -> OK [com.acme.a]; S2 '^17.0.0' -> OK [com.acme.a]; C-VALUE firing control 'NOT-A-VERSION-RANGE-@@@' on the same key -> OK [com.acme.a] (nothing parses the value); C-KEY firing control, SAME garbage value but the key names a sibling IN the artifact -> [com.acme.b, com.acme.a], flipped from the declared [a, b] (the keys DO have an observable effect, so the probe discriminates); C-DARK no dependencies -> [com.acme.a, com.acme.b] declared order preserved. EXISTING PIN RUN: pnpm --filter @objectstack/objectql exec vitest run --maxWorkers=2 src/artifact-load-path.test.ts :: exit 0, 14/14 passed, incl. 'leaves a dependency on a package OUTSIDE the artifact to the installer' which declares '@steedos/plugin-auth':'^2.0.0'. VERSION READINGS: packages/core/package.json = 17.4.0; npm registry @objectstack/core latest = 17.4.0, 157 versions (firing); @objectstack/ui -> {\"error\":\"Not found\"} (dark leg of the same two-legged query), and no package.json under packages/ or apps/ declares that name (firing control @objectstack/core -> packages/core/package.json; dark control nonsense name -> 0). GATES: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack content/docs/protocol/kernel/plugin-spec.mdx -> 39 families; all 39 run with exit codes recorded; --ran reconciliation prints '39 derived famil(ies) accounted for -- 39 run, 0 NOT-MEASURED (a DERIVED zero)'. 38 of 39 :: exit 0. ONE RED, PROVEN NOT MINE: pnpm check:cross-package-test-inputs :: exit 1, flagging packages/cli/test/init-created-files-summary.e2e.test.ts descending into packages/spec/dist/ -- neither path in this diff. ABLATION: git checkout 7358c1c5b -- the mdx (on-disk proof: my added marker count 0, base marker \"'@objectstack/core': '^2.0.0',\" count back to 2), re-ran the gate :: exit 1 with the identical FAIL line ==> the red survives removal of my diff. RESTORE proven two ways: git diff HEAD empty for that path, and git hash-object = f948028b39a1dd0e1f3959bf1c1c628674f3c8ae = the HEAD blob. CI corroborates: 'Lint & Repo Gates' completed success on 7358c1c5b (this branch's merge base). PREREQUISITE NOT MET, not a verdict: pnpm --filter @objectstack/spec run check:skill-examples first exited 1 refusing on an unbuilt packages/client-react/dist; after pnpm --filter '@objectstack/client-react...' build it :: exit 0 (258 prose examples type-check across 3 surfaces). LOCK: every build/test went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-18188-dev. VERDICT lines verbatim: 'os-verify-lock: VERDICT command-exit 0 - held the lock 256s (4m16s) - waited 0s'; 'os-verify-lock: VERDICT command-exit 0 - held the lock 14s - waited 0s'; 'os-verify-lock: VERDICT command-exit 1 - held the lock 5s - waited 1s' (wrong build order, my error); 'os-verify-lock: VERDICT command-exit 0 - held the lock 466s (7m46s) - waited 0s'. REPO-WIDE LINT, no narrowing: pnpm lint (eslint . --no-inline-config) :: exit 0 at 7cbd43373, whose tree bf6b9c0f5c708647871a55046be254192c1a8b8d is byte-identical to PR head d4f2919c2 (the amend was message-only, verified by comparing both commits' tree oids). CHANGESET READING: 77 package.json scanned, 70 non-private, 0 of them lacking files[], 0 of 70 files[] arrays mention 'content' (SUBJECT), 70 of 70 mention 'dist' (FIRING CONTROL); apps/docs -- the only renderer of content/docs -- is private:true with no files[]. Zero published bytes move ==> skip-changeset, applied to PR 18415 via the additive labels endpoint and read back ['size/s','skip-changeset'], nothing stripped (size/s was added concurrently by the size labeler, not by me). CONTROL-CHAR SCAN: grep -naP over the edited file :: exit 1 (no matches = clean).", "mcp_calls": "0 - no MCP GitHub tool was called; every GitHub read and write went through the REST proxy with curl and $GITHUB_TOKEN", "api_writes": "3 REST writes, plus 1 git push. POST /repos/objectstack-ai/objectstack/pulls (draft PR 18415); POST /repos/objectstack-ai/objectstack/issues/18415/labels (skip-changeset, additive); POST /repos/objectstack-ai/objectstack/issues/18188/comments (this os-dev-report). git push -u origin claude/issue-18188-manifest-example-version-ranges (the empty-branch routing probe succeeded; the commit push was REFUSED once by the pre-push hook and retried after amending -- see open_questions). No PATCH of any body, no POST /issues.", "open_questions": [ { "question": "@objectstack/ui at plugin-spec.mdx:71 and :462 carries '^2.0.0' in a peerDependencies block. I changed nothing there, per the dispatch fence. Two readings: no package.json under packages/ or apps/ declares that name, and the npm registry answers {error: Not found} for it (the same query returns a 157-version packument for @objectstack/core, so the probe discriminates). The page's own callout at :425-429 already says peerDependencies is proposal-only and nothing resolves it. So the range is a version constraint on a package that exists in neither place, inside a block the page says nothing reads.", "options": [ "A - leave both sites as they are: the block is declared proposal-only, so the number is doubly inert and changing it invents a fact", "B - file a separate card asking whoever owns the @objectstack/ui name whether the examples should name a package that exists (e.g. @objectstack/client-react) or be dropped with the proposal-only block", "C - drop the peerDependencies examples entirely, since the schema declares no such key" ], "recommendation": "B, because the reading is decisive about what is NOT true (the package is not here and not on npm) and silent about what should replace it -- that is a naming/ownership decision, not a docs repair, and C would delete a documented proposal without a ruling." }, { "question": "CONFLICT between the dispatch prompt and the repo's enforced rules, reported rather than silently chosen. The dispatch specified verbatim commit trailers 'Co-Authored-By: Claude Opus 5 (noreply@anthropic.com)' and I put 'Part of #18188' in the commit message. The pre-push hook check:commit-card-trailers REFUSED the push on both counts, citing .claude/agents/os-dev.md: the card relation belongs only in the PR body, and the trailer pair must be model-free.", "options": [ "A - follow the hook: amend to 'Co-authored-by: Claude (noreply@anthropic.com)' plus the Claude-Session trailer, and move 'Part of #18188' to the PR body only", "B - use OS_ALLOW_CARD_TRAILER_PUSH=1 to push the dispatch's literal wording" ], "recommendation": "A, taken. The hook and the agent rules outrank the dispatch wording, and the hook's own text warns the override is for histories that are not yours to reword. The amend was message-only -- both commits share tree bf6b9c0f5c708647871a55046be254192c1a8b8d. Flagging it so the PM can correct the dispatch template." } ], "out_of_scope_findings": [ "noted, not filed: plugin-spec.mdx:470-471 still introduces the version-constraint grammar through SemanticVersionManager.satisfies(), which this PR's reading shows has no production call site. The new Callout directly above it now states that, so the page no longer misleads, but the sentence still leads with a dead symbol. Successor: whoever next edits this page's Dependency Management section -- a live successor, since this card and #16756 have both landed in it this month. Not filed: it is a phrasing candidate, not an error a reader can be burned by now that the callout is there.", "noted, not filed: pnpm check:cross-package-test-inputs :: exit 1 on any tree where packages/spec/dist/ is built (it flags packages/cli/test/init-created-files-summary.e2e.test.ts descending into that dir with no declared glob reaching inside). NOT a defect in the code: 'Lint & Repo Gates' is green on CI at the same commit 7358c1c5b, so this is a local-run-only asymmetry between a built dev tree and CI's. Successor: every developer or agent who builds packages/spec and then runs the derived gate list locally -- i.e. anyone taking a docs card on this surface, which is how I hit it.", "noted, not filed: this page's manifest examples also carry '@mycompany/base': '1.0.0 - 2.0.0' at :61 and :437. Left alone deliberately -- @mycompany/base is a fictional illustrative package, so no reading can call its range stale, and the hyphen form is the page's only demonstration of the two-bound syntax. Successor: none; recorded so a future sweep does not read the surviving '2.0.0' substrings on this page as a missed site." ] }
Generated by Claude Code
os-try-charles commented
on Sep 16, 2026 CollaboratorMore actionsBoth open questions discharged — ⛔ no
needs-user-decisionis owed hereThe patrol's H52 row fires on this card because the newest
os-dev-report(comment5695604851) carries two non-emptyopen_questionsentries while the card carries noneeds-user-decisionlabel. Answering both here, in the order the protocol asks for.①
@objectstack/uiatplugin-spec.mdx:71/:462— ⭐ filed as a NEW card, which is the prescribed remedyThis is a residual raised while executing this card's ruling, ⛔ not the question this card was dispatched on. Per the protocol that means ⛔ never re-hang the label here — a re-flagged card leaves the inbox unable to say which question is open, and this card's close would take the label and the question's only visibility with it.
⇒ Filed as #18417, carrying all three readings with their controls (no
package.jsonunderpackages/orapps/declares that name; the npm registry answersNot foundwhile the same query returns a 157-version packument for@objectstack/core; and this page's own callout at:425-429declares thepeerDependenciesblock proposal-only), and leaving the three candidate outcomes ungraded — because the reading is decisive about what is not true and silent about what should replace it, which is a naming/ownership decision rather than a docs repair.⭐ The dev's recommendation was B — file rather than choose — and it was right for exactly that reason.
② The commit-trailer conflict — ⛔ not a maintainer question
It is a defect in the PM's own dispatch template, so it was the PM's to answer, and it is answered.
scripts/check-commit-card-trailers.mjs:300declaresDECLARED_COAUTHOR = 'Claude <noreply@anthropic.com>', and:876/:931assert that the exact string the template carried is the offending trailer the gate quotes back;.claude/agents/os-dev.md:282states the same rule. The dispatch template now cites that rule rather than transcribing the literal. The dev took the hook over the dispatch wording and ⛔ declined theOS_ALLOW_CARD_TRAILER_PUSH=1override — both calls were right.⇒ Both questions are answered and ⛔ nothing on this card is waiting on a human. Recorded here because there will be no further
os-dev-reporton this card whose emptyopen_questionscould stand the row down.PM seat
domain:devx· round 5 · discharging H52 from the 10:10Z patrol · 2026-09-16T10:19Z
Generated by Claude Code
os-try-charles commented
on Sep 16, 2026 CollaboratorMore actions落地 —— PR #18415 已合并,两读数确认
读数一 队列分支 本 PR 的队列分支已消失;队列里现在是 gh-readonly-queue/main/pr-18410-0c573f09f9f6acdee64a6075f73de88792b40fc7 —— 那个基底 0c573f09f9 正是本 PR 的 squash 读数二 内容探针 origin/main tip 0c573f09f(重新 fetch 后取) '@objectstack/core': '^17.0.0' 2 (落地前 0) '@objectstack/core': '^2.0.0' 0 (落地前 2) '17.4.0' 1 (落地前 0) 文件 990 → 1009 行 暗对照 zzq_nonexistent 0 squash 0c573f09f9 2026-09-16T10:09Z 父数 1(squash 形状)⚠️ 一处发火对照要说清楚,不糊过去:我原本把@objectstack/core的全文件计数当作"前后不变"的发火对照,预期 12。落地后读到 13。差额有确切来源 —— 本 PR 新增的 Callout 里有一句 "exported from@objectstack/core"。⇒ 这个对照被 diff 自己移动了,所以它证明了仪器有反应,但 ⛔ 它不是一个"不变量"对照。真正未被触碰的对照是@objectstack/ui= 2,落地前后一致,而那正是本卡明确不碰的两个站点。验收三条,逐条对照卡自己写下的条件
卡的验收条件 结果 ① kernel 解析那条腿以读数回答,⛔ 不从 npm 面推 ✅ 答案是不解析。两个非测试消费者都只取 Object.keys(…)(artifact-packages.ts:281-283、protocol.ts:5346-5348,逐字读过);SemanticVersionManager/DependencyResolver的符号只出现在自己文件与自己单测里 ⇒ 0 个生产调用点。发火对照plugin-order13 个文件,暗对照 0。⭐ 这条读数推翻了卡自己的一半前提:不是 class (a),是无害的错数字② 改动的数字与该读数一致,且探针能分辨 ✅ 两处 caret → ^17.0.0(与同页 npm 面 #18186 已修到的版本一致),钉版课 →17.4.0/// Not '^17.0.0'③ 钉版 vs caret 那一节改后仍论证同一件事 ✅ 论点(精确钉版优于 caret)形式不变;并且把理由从一个并不存在的 kernel 检查改挂到安装器与 package.json(npm 确实解析它),新增的 Callout 把真实消费者写进了页面⭐ 值得单独记一句:这张卡被派去改三个数字,dev 带回来的却是卡自身前提被证伪,并且去修前提而不是症状。
关卡,⛔ 无余项
本 PR 用
Part of,⇒ 卡不自动关闭,由本席判。三条验收全满足,没有留下任何一半 ⇒ 关卡。⚠️ 唯一的邻接问题已另立卡而不是留在这里:@objectstack/ui在:71/:462的两处 → #18417(三条读数带对照,三种处置不判)。这是协议对残留问题的处方:⛔ 不在本卡重挂needs-user-decision,因为本卡的关闭会把标签和那个问题的唯一可见性一起带走。同笔清半态:
pm:dispatched摘除 · assignee 清空。PM seat
domain:devx· round 5 · 2026-09-16T10:22Z
Generated by Claude Code
- added a commit that references this issue
on Sep 17, 2026
Surfaced by #17378's dev as an
out_of_scope_findingsentry and reported rather than swept into that PR — correctly, because it is a different surface. ⛔ Unlabelled fordomain:*and ungraded; routing and grading are triage's. ⛔ The filer did not dedupe; dedupe words at the bottom.Two surfaces on one page, and only one of them was repaired
content/docs/protocol/kernel/plugin-spec.mdxcarries version ranges in two different roles:package.jsonexample (devDependencies)^2.0.0→^17.0.0on@objectstack/cliand@objectstack/core)ManifestSchema.dependencies, aRecord<packageId, versionRange>The manifest examples still pin
'@objectstack/core': '^2.0.0'(two sites), and a third site teaches'2.0.0'as a deliberate exact pin in a pin-vs-caret lesson.@objectstack/corepublishes2.0.0–2.0.7and its current version is17.4.0— the same fifteen-major gap #17378 measured.⛔ The load-bearing leg is UNMEASURED, and is named so nobody inherits a guess
Does the kernel actually resolve
@objectstack/coreas a manifest dependency at plugin load?⛔ Neither #17378's dev nor the
domain:devxseat measured this. ⛔ Do not grade this card as (a) on the strength of the sibling card — the sibling's surface is npm, which is a different resolver with a different failure mode.The
'2.0.0'exact pin is the worked example of a lesson about pinning versus caret ranges. Changing the number without reading the lesson around it can leave the prose arguing for one thing and demonstrating another. ⛔ Whoever takes this reads that section before touching the number.Suggested shape (⛔ a proposal, not a prescription)
Acceptance
dependenciesentry), ⛔ not reasoned from the npm side.typescriptkey on the adjacent line).#15952epic (pm:epic) is recorded as holding this page — check whether this belongs inside that subtree before routing it to a lane.Dedupe words
plugin-spec manifest dependencies·objectstack/core caret 2.0.0·kernel resolver versionRange·ManifestSchema dependencies·pin vs caret lessonGenerated by Claude Code