Skip to content

docs(devx): reciprocal pointers for the invoked-as three-copy sync obligation - #12084

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-12013-invoked-as-reciprocal-pointers
Aug 25, 2026
Merged

docs(devx): reciprocal pointers for the invoked-as three-copy sync obligation#12084
yinlianghui merged 1 commit into
mainfrom
claude/issue-12013-invoked-as-reciprocal-pointers

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Fixes#12013

What

Both objectstack copies of the argv[1]-vs-import.meta.url entry-point predicate — scripts/invoked-as.mjs (isEntrypoint/invokedAs) and packages/cli/src/utils/invocation.ts (isProcessEntry) — named only each other. Neither pointed at the third copy, objectui's own scripts/invoked-as.mjs, which already carries "All three copies … Change one, change the others". An agent editing either objectstack file had no way to discover the third copy exists.

Comment-only, both files:

  • scripts/invoked-as.mjs: the local-sibling section is retitled ## The siblings, and why the duplication is deliberate (matching objectui's heading verbatim) and gains one paragraph naming objectui's scripts/invoked-as.mjs; the closing sentence is updated from "Both carry … Change one, change the other" to "All three copies carry … Change one, change the others" — mirroring objectui's merged wording.
  • packages/cli/src/utils/invocation.ts: the isProcessEntry docstring gains one paragraph naming both siblings (this repo's scripts/invoked-as.mjs and objectui's).

Neither file's existing prose is corrected or otherwise touched — both were already accurate for this tree (triage ruling, confirmed below).

Zone 2 — what I measured, against the PM's assumptions

  1. Premise, re-measured on origin/main = f7b25c546 (matches the claim comment): scripts/invoked-as.mjsobjectui × 0, change the others × 0, invoked × 15 (positive control, file really read). packages/cli/src/utils/invocation.tsobjectui × 0, change the others × 0, 186 lines. Premise held; neither file carried a back-pointer.
  2. objectui wording to mirror. objectui PR [finding] Check Changeset 在 opened 事件上先于 skip-changeset 标签落地而判红 —— 每个走 skip 路线的 PR 都要白跑一次重投(今日 6 例) #6260 is merged (state: closed, merged: true, squash-merged as objectui@ef2a3bd8d8a12957d565748cff0eb47cf03ee548, 2026-08-25T05:20:54Z). Read its merged scripts/invoked-as.mjs directly off objectui:main. The ## The siblings, and why the duplication is deliberate section's final sentence, verbatim (one placeholder spelled in words below since GitHub's body sanitizer strips a literal angle-bracket fragment even inside a code span): "The duplication is therefore structural, but DIVERGENCE is not allowed -- two predicates answering this question differently is precisely the defect being closed. All three copies carry the same two legs: realpath for symlinks, and directory resolution for node given a directory argument. Change one, change the others." Mirrored into both objectstack files (heading text and closing sentence); the new middle paragraph in each is original, since objectui's own version only had to name objectstack's two copies, while each objectstack file has two different siblings to name (its local counterpart, already named, plus objectui).
  3. Gate families, re-derived in my own worktree (not the shared checkout) via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, run before and after adding the changeset: 23 families matched the actual diff, exactly reproducing the PM's 17 pre-changeset + 6 changeset-triggered lists, no additions or omissions on my re-derivation. All 23 green below, plus the standing check:nul-bytes clause.
  4. check:entry-guard and scripts/invoked-as.mjs --self-test — confirmed unaffected: self-test still reports 11 cases pass, check:entry-guard still reports the same shape (157 files, 113 bindings, 111 inert). Docblock-only edit, as assumed.
  5. Changeset determination, derived rather than guessed: scripts/check-empty-changeset.mjs and the pr-automation.yml "Require a changeset" step do not do per-file path analysis in this repo (unlike objectui's check-changeset-presence.mjs, which objectstack has no equivalent of) — the CI gate is a binary author-judgment call (real changeset vs. skip-changeset label), and check:changeset-gate-self-tests only pins the checkers' own fixtures, not this PR's paths. The operative rule is the devx lane doc's own text (.claude/skills/pm-dispatch/references/lanes/devx.md): "changeset 按 publish 面判:根 scripts/ / docs / test-only ⇒ skip-changeset;落进已发布包的源 ⇒ 真 changeset" — tied to file location, not content. packages/cli is published ("name": "@objectstack/cli", "version": "17.2.0", no "private"), and the edit lands in its src/. Precedent in .changeset/cli-readme-drop-os-studio.md — a patch changeset for a pure prose correction to packages/cli/README.md, not even compiled source — confirms this repo's convention treats "lands in a published package" as sufficient regardless of whether the change is behavioral. So: real changeset added (@objectstack/cli: patch), not the label. scripts/invoked-as.mjs alone would qualify for skip-changeset, but the rule has no per-file carve-out at PR granularity, and the packages/cli edit governs the whole PR.

Cross-repo note

Read-only against objectstack-ai/objectui, ref main (post-merge of #6260) — no objectui file touched, branched, or opened by this PR.

Verification

All commands run in a dedicated worktree (../objectstack-12013), heavy ones serialized through scripts/pm/os-verify-lock.sh. Verdicts below are each gate's own printed line, exit code captured before any pipe. Final commit: 258b2cadf.

Dependency-build prerequisite (unrelated to this diff — a stale dist/ in this fresh worktree, not a defect): pnpm --filter '@objectstack/example-showcase^...' build was needed before check:i18n-coverage could measure all 12 configs; after that it read OK (12 config(s), 657 baselined untranslated string(s), none new).

gateverdict
pnpm --filter '@objectstack/cli' buildrc 0 (tsc compiles cleanly with the added docblock)
pnpm --filter '@objectstack/cli' typecheckrc 0
pnpm --filter '@objectstack/cli' exec vitest run --maxWorkers=2 src/utils/invocation.test.tsTest Files 1 passed (1) · Tests 17 passed (17)
node scripts/invoked-as.mjs --self-test✓ invoked-as self-test: 11 cases pass …
pnpm check:entry-guard✓ check:entry-guard: 157 scripts/ file(s) … every entry guard goes through invoked-as.mjs; 113 export bindings, 111 of them inert on import (2 known-unsafe, ⛔ SHRINK-ONLY)
pnpm check:agent-test-spelling✓ check-agent-test-spelling: 0 violations …
pnpm check:cross-package-test-inputsOK: 16 package(s) read outside themselves, all declared …
pnpm check:i18ncheck-i18n-bundles: OK (9 package(s) — all bundles in sync, no undeclared authoring keys).
pnpm check:i18n-coveragecheck-i18n-coverage: OK (12 config(s), 657 baselined untranslated string(s), none new).
pnpm check:parse-guardrc 0
pnpm check:pnpm-filter-targets✓ check:pnpm-filter-targets: 135/168 …
pnpm check:published-files✓ check:published-files — 69 publishable package(s) of 78 …
pnpm check:slot-lookup✓ slot-lookup ratchet holds: 107 unswept site(s) …, none new
pnpm check:test-source-aliascheck-test-source-alias OK — 72 packages with tests scanned …
pnpm check:type-source-resolutioncheck-type-source-resolution OK — 93 tsc program(s) across 77 packages scanned …
pnpm check:changeset-gate-self-testsall 3 sub-checkers' self-tests pass
pnpm check:objectui-changeset✓ objectui-range --self-test: all checks passed
node scripts/check-adr-0087-registration.mjs✓ … this PR adds no declared-breaking changeset (0 non-breaking changeset(s) seen).
node scripts/check-changeset-no-major.mjs✓ This diff introduces no 'major' bump.
node scripts/check-ci-filter-parity.mjsOK: all 96 declared cross-package glob(s) …
node scripts/check-cross-package-test-inputs.mjsOK: 16 package(s) read outside themselves …
node scripts/check-empty-changeset.mjs✓ No empty-frontmatter changeset introduced by this diff (0 declaring changeset(s) added).
node scripts/check-plugin-teardown-shape.mjs✓ … 0 known-unreached, ⛔ SHRINK-ONLY, baseline fully burned down.
node scripts/docs-audit/check-affected-docs.mjsrc 0, ✓ affected-docs self-test: 451 cases pass.
node scripts/docs-audit/check-drift-comment.mjs✓ check-drift-comment: 56 cases pass across 5 fixture diff(s).
node scripts/pm/release-rehearsal-clone.mjs --self-test✓ self-test passed
pnpm check:nul-bytes (standing clause)check-nul-bytes: OK … no raw ASCII control bytes.

Control-byte self-scan (grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' on both edited files): no matches.


Generated by Claude Code

…ligation
Both objectstack copies of the argv[1]-vs-import.meta.url entry-point predicate
(scripts/invoked-as.mjs's isEntrypoint/invokedAs, and packages/cli/src/utils/
invocation.ts's isProcessEntry) named only each other. Neither pointed at the
third copy, objectui's own scripts/invoked-as.mjs (which already names both
objectstack copies and states "All three copies ... Change one, change the
others", merged in objectui PR #6260 / objectui@ef2a3bd). An agent editing
either file in this repo had no way to discover that a third copy exists and
must move with it.
Comment-only, both files: the local sibling section in scripts/invoked-as.mjs
is renamed "## The siblings" and gains one paragraph naming the objectui copy;
packages/cli/src/utils/invocation.ts's isProcessEntry docstring gains one
paragraph naming both siblings. Neither file's prose is otherwise corrected —
both were already accurate for this tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️1 changed file(s) yielded no anchor (packages/cli/src/utils/invocation.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/cli/src/utils/invocation.ts) — pages documenting those are invisible to this run
  • 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.

Coarse fallback — 23 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 402113d57da22a97f7f7a07587f860cfecb60a02packageMentionDocs.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tooling labels Aug 25, 2026
@yinlianghui
yinlianghui marked this pull request as ready for review August 25, 2026 08:41
@yinlianghui
yinlianghui added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 93949f1Aug 25, 2026
35 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-12013-invoked-as-reciprocal-pointers branch August 25, 2026 08:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/stooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The invoked-as three-copy sync obligation is visible from only one of its three ends

2 participants

@yinlianghui@claude