Repository navigation
Migrate documentation site to Fumadocs with monorepo structure and shared content - #11
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
…rver Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add setup for Fumadocs documentation site
Migrate documentation site from custom @objectdocs/cli to Fumadocs
Jan 18, 2026
Contributor
|
@copilot nextjs项目使用多包架构放到apps/docs,不要污染根目录 |
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Contributor
Author
Done! The Next.js documentation site has been moved to Changes:
See commit 3124fe9 for the complete restructuring. |
Copilot
AI
changed the title
Migrate documentation site from custom @objectdocs/cli to Fumadocs
Migrate documentation site to Fumadocs with monorepo structure (apps/docs)
Jan 19, 2026
Contributor
|
@copilot 我的文档还是放在很目录,不要换位置 /content/docs |
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Contributor
Author
Done! Documentation content is now kept at the root directory Changes:
The Next.js app remains in See commit c60ebe7 for the changes. |
Copilot
AI
changed the title
Migrate documentation site to Fumadocs with monorepo structure (apps/docs)
Migrate documentation site to Fumadocs with monorepo structure and shared content
Jan 19, 2026
…mprove documentation formatting, and refine build scripts
This was referenced Sep 3, 2026
This was referenced Sep 4, 2026
This was referenced Sep 10, 2026
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 17, 2026
…orktree path, and make the self-test exit non-zero when it fails (objectstack-ai#18165) Fixes objectstack-ai#17602 ## PREMISE P was measured first, and it HOLDS — so the driver is not the defect The card asks whether a zero exit from `merge=os-regen` can be trusted. The `domain:devx` seat's mechanism reading (comment `5631161285`) narrowed that to one falsifiable premise: is `content/docs/references/**` really "generated whole", as `.gitattributes:84` declares? If yes, the unconditional deferral is the design and `markPending` + regeneration closes the loop; if no, the row is MIXED without a `mixed` field and the deferral is a silent deletion — and the defect would be in the declaration. Measured on `origin/main` `394ccf549`, with the post-driver state reproduced exactly (the artifact missing main's side while the source still carries it), the generator re-run, and both controls lit: ``` before mutation after mutation after gen:docs main's #groupBy whitespace note 2 0 2 <- P FIRING CONTROL (marker injected into the mdx) 0 1 0 EMPTY CONTROL (a string never written) 0 0 0 blob sha of content/docs/references/ui/view.mdx HEAD 2fa435c mutated 2e40a12d888d9babaa254974a69b3feece62a93a (the mutation landed on disk) regenerated 2fa435c (byte-identical to HEAD) ``` The note is not hand-written: it is a `.describe()` at `packages/spec/src/ui/view.zod.ts:917`, rendered into the page by `gen:docs`. The firing control proves the generator rewrites this file wholesale rather than skipping or appending — the injected marker is gone. Regeneration reproduces the page **byte for byte**. ⇒ `.gitattributes:84` is true for this family. `scripts/git-merge-regen.mjs` behaved exactly as its own comment says it should, and ⛔ nothing in this PR changes the driver's merge behaviour, weakens a gate, adds an exemption, or makes the driver prefer a side in a new case. ## So the work is ask 2 — and the safety net DOES hold, but nothing proved it The remaining question is the one the ruling names: on the path this incident took — a human or agent hand-repairing a merge **in a linked worktree** — does the refusal actually fire? Measured live, in this worktree, with a real merge of a real routed path: ``` git merge exit 0 (the card's zero exit, reproduced) marker written to .git/worktrees/.../os-regen-pending YES the ordinary commit right after REFUSED by .githooks/pre-commit the push REFUSED by .githooks/pre-push ``` The net holds. What is unguarded is that **no test says so.** The driver ends every deferral by *printing* "The pre-commit hook will not let this commit through until you do", and the two cases that come closest each stop one step short in the same direction: - `endToEnd()` performs a real merge, asserts the marker exists, and never commits — so git never runs a hook. - `check-regen-pending.mjs`'s deferred-merge fixture sets `core.hooksPath=/dev/null` ("the fixture drives the script itself") and writes the marker by hand — it grades the checker's verdict, never git's willingness to invoke it, and never the path the driver wrote to. The joint property had no coverage at all, and the one arrangement in which it can break is the one AGENTS.md Prime Directive objectstack-ai#11 makes mandatory. `markPending()` in the driver and `gitDirPath()` in the checker are two **independent** `--absolute-git-dir` call sites; in a primary checkout that directory and `--git-common-dir` are the **same directory**, so a regression to the common dir keeps every single-tree fixture green while every real merge in every agent's worktree silently loses its refusal. ## What landed **1. `endToEndWorktreeRefusal()` — a sixteenth self-test battery.** It builds a throwaway repo with a linked worktree, reaches the REAL `.githooks` and the REAL checker through untracked symlinks (so the *relative* `core.hooksPath` resolves per worktree, as `setup-git-hooks.mjs` registers it — a hook this file wrote out would test an imitation), merges a routed path inside the linked worktree, and asserts nine legs: | leg | assertion | |---|---| | 1 | the marker lands in the LINKED worktree's own git dir | | 2 | …and NOT in the shared common git dir — the discrimination only a linked worktree can make | | 3 | the ordinary commit after the merge is REFUSED, by git, through the real `pre-commit` | | 4 | …naming the artifact, so the refusal is this one and not some other failure | | 5,6 | the push is REFUSED too, by the real `pre-push`, via its os-regen leg | | 7,8,9 | **FIRING CONTROL** — with the gate clean the same commit is ACCEPTED, the marker is gone, and the push goes through | Legs 7-9 are what legs 1-6 rest on: a hook that can only fail — a missing interpreter, a typo'd path, node erroring — satisfies every refusal assertion while proving nothing, and from the outside that reads exactly like "the net holds". **2. The self-test's exit code now agrees with its own verdict.** Found by the ablation below, not by reading. The `--self-test` dispatch computed `failures` from the booleans its callees return and printed `✗ merge driver wiring is inconsistent — N failure(s)` from that count — then exited **0**. The only thing that ever set a non-zero code was `fail()`, which every callee happened to call. The two agreed by convention, not by construction, and `pnpm check:merge-driver` chains this file with `&&`: the first callee to report a failure by returning `false` alone would have made the whole battery advisory. The verdict line and the exit code now come from the same count. This is an in-place fix under the bounded exemption — same defect class as the card (a failed check reporting as a pass), mechanical, on a file this PR already declares, in the same gate family, adding no new verification surface. ## Ablation — the battery can fail, and the existing cases cannot catch what it catches `markPending()` regressed to the shared common git dir (the exact regression class the case exists for), run from the committed state, mutation proven on disk before the run and the restore proven byte-identical after: ``` occurrences of the replaced line 1 -> 0 injected marker 0 -> 1 blob sha HEAD 4506a6d -> ebd8f1077e725251161a067d50905c3d8b116c10 self-test exit under the ablation 1 (before fix 2: 0 — see above) ✗ endToEndWorktreeRefusal — all six refusal legs red, firing control red ✓ end-to-end: conflicting packages/spec/spec-changes.json … recorded as pending <- STILL GREEN ✓ end-to-end (mixed): anchors-only deferred to OURS … <- STILL GREEN ✓ probe gate: `git merge-tree` reaches the driver and records nothing <- STILL GREEN restore: blob sha back to 4506a6d…, residual injected text 0, `git diff HEAD` empty ``` Three pre-existing end-to-end cases stay green through a regression that disarms the refusal for every worktree in the container. That asymmetry is the case's whole justification. ## Which of the three unreliable signals this makes trustworthy Triage `5628590957` records three cards describing one apparatus whose every signal is unreliable, and asks which one a change repairs. This PR repairs **the driver's exit code being the only evidence the merge was safe** (objectstack-ai#17602): after it, the claim "the hook refuses until regeneration has run" is a test rather than a sentence, on the path real merges take. It also, incidentally, moves **objectstack-ai#13799**'s signal for this one member: the `os-regen-merge` self-test (`.github/workflows/lint.yml`) is named in objectstack-ai#13799's population, and fix 2 means that battery can no longer report a failure at exit 0. ⛔ That is one member, ⛔ not objectstack-ai#13799. It does **not** touch **objectstack-ai#16717** — `check:merge-driver` remains red on macOS for the runner-missing classifier's reasons, so a green local run of this battery is not evidence there. The new case is platform-neutral (git, symlinks, `pnpm -s` on a stub), but it inherits objectstack-ai#16717's blind spot like every other case in the file. ## Effect on objectstack-ai#16612 (shares this file, serialized behind this card) **Neither easier nor harder — but it is now instrumented.** objectstack-ai#16612 proposes retiring the only `mixed` row, which would drop `system-context.mdx` onto the unconditional-deferral branch this card measured. Nothing here changes that branch. What changes is that whoever takes objectstack-ai#16612 now has a case that proves the deferral's refusal actually fires end to end, so the question "is the safety net behind the deferral real?" is answerable by running `pnpm check:merge-driver` instead of by argument. ⛔ Not fixed in passing; ⛔ not re-priced here. ## Gates `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived **32** commands from the real diff (1 path, `scripts/git-merge-regen.mjs`, vs merge base `394ccf549`). All 32 run and exit 0, reconciled with `--ran`. Exit codes landed to disk per command. `pnpm check:merge-driver` — the gate that owns this battery — is among them. `pnpm lint`'s scan was not narrowed and needs no narrowing argument: the whole set ran at `3d8e4c63e` — `eslint . --no-inline-config --format json` over **6752** files, **0** errors, **0** warnings. (The config declares it never enables type-aware linting for any file, so a one-file diff could not have moved another file's verdict in any case.) changeset: **`skip-changeset`**, measured rather than assumed. The diff is one root `scripts/**` file; the root package is `private: true`; all 70 published packages declare `files[]` and none can reach root `scripts/`; the new symbol occurs in zero published package sources, against a lit positive control (`defineStack` hits in `packages/spec/src`). ## Acceptance notes - `SELF_TEST_BATTERY_FLOOR` moved 15 to 16 and the roster/dispatch gained the new callee, as that mechanism requires. The callee-count prose in the same block moved with it; one number there ("the other thirteen") was already off by one against a roster of fifteen and is now correct at fifteen against sixteen. Mechanical, in the block being edited. - Noted, not filed: `check-regen-pending.mjs`'s deferred-merge fixture still sets `core.hooksPath=/dev/null` and writes its marker by hand. That is deliberate and correct for what it grades (the checker's verdict machine), and the new case covers the half it cannot; a second end-to-end fixture there would duplicate it. Successor: whoever next widens that fixture's scenario set. - Noted, not filed: the driver's `--self-test` prints its verdict and, before this PR, derived its exit code elsewhere. The sibling self-tests chained beside it in `check:merge-driver` (`git-env.mjs`, `check-regen-pending.mjs`) were not audited for the same shape — out of scope here, and neither is known to have it. Successor: none currently queued. --- _Generated by [Claude Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 29, 2026
veigajoao
pushed a commit
to veigajoao/objectstack
that referenced
this pull request
Sep 29, 2026
…mes a known repository, so pre-#N / post-#N are judged and framework#N is this repository (objectstack-ai#20554) Fixes objectstack-ai#20330 Clause-②: no ## What changed `scripts/check-issue-citations.mjs` read ANY `word#N` as a repository reference, so `pre-objectstack-ai#12248`, `post-objectstack-ai#6640`, `Pre-#N`, `POST-#N` and `Framework#N` were classed cross-repo and never judged. Its qualifier is now a **closed set**. A token joined to `#N` names a repository only when it is an `owner/repo` form or a name in the new `KNOWN_REPOSITORIES` table, matched case-insensitively. Any other prefix is prose, and the number after it is this repository's and is judged. One recogniser, `repositoryOf`, is asked in all three places: by extraction, by the board's probe set (`boardWanted`) and by the classifier (`namesThisRepository`). The three can no longer disagree about a token. - `KNOWN_REPOSITORIES` rows: `objectstack` and `framework` (both THIS repository), `objectui`, `ui` (an objectui alias, joined form only), `cloud`, `hotcrm`, `hotcrm-heimao`, `os-tianshun-mtc` and `os-project-titanwind-ehr`. Each row carries the measurement that put it in. - **Prose form.** `objectui PR objectstack-ai#10264`, `objectui objectstack-ai#2670`, `cloud objectstack-ai#2937` and `framework objectstack-ai#2679` read as their repository. The form is a known repository name, whitespace, an optional `PR` or `issue`, then `#N`. The alias `ui` is excluded from it, because `UI #N` is ordinary English. - **No carry across a pair.** In `objectui#6110 + objectstack-ai#6111` the second number stays this repository's. The convention is to qualify each number, and the one live site in the claim's surface is respelled: `packages/spec/src/data/field.zod.ts:370` now reads `objectui#6110 + objectui#6111`. This is comment-only, with a `patch` changeset. - **Ordinal heads.** Closing the set exposes ordinals that were hidden behind a fake qualifier. `NON_CITATION_HEADS` gains `OQ` (`ADR-0076 OQ#10`, 10 sites) and `PKCS` (`PKCS#11`, 1 site). A hyphen joining a head to its `#` is now read as the same head (`Prime-Directive-objectstack-ai#12`, 2 sites). `PD#12` (8 sites) was already covered by the existing `pd` head once its candidate is refused. - **Refusal text.** The `REMEDY` text now states the grammar that judged the author. ### A false red in the same seam, fixed because this change would have widened it `buildBoard` probed only UNQUALIFIED numbers, so a diff adding `objectstack#N` was classified against a board that never asked about N. Reproduced on unmodified `288611e3e5`: I appended `objectstack#20330` (this live card) to a swept file and ran `node scripts/check-issue-citations.mjs`. It exited **2**, reading `board: probed (0 citations)` and `[allocated-but-absent] ... objectstack#20330`. Reading `framework#N` as this repository would have inherited that false red on every site. The probe set is now `boardWanted`, meaning every citation judged here. The self-test pins it through `probeBoard` over a stub. The blocking rule is unchanged: findings still exit 2. ## Measurements the design rests on - **`framework` names this repository.** `git ls-remote https://github.com/objectstack-ai/framework` answered HEAD `288611e3e5`, identical to `objectstack-ai/objectstack`. The controls diverged: a nonexistent name under the same owner exited 128, and `objectstack-ai/objectui` answered its own HEAD `0eb9f36aca`. The REST and web routes to `framework` answered 403 from this session's proxy (bound to configured repositories), so git's rename redirect was the readable instrument. `framework#N` / `Framework#N` therefore read as THIS repository. - **Qualifier census on `288611e3e5`, over the declared surfaces.** There were 27 distinct candidates behind 1,655 sites: - This repository: `framework` 255, `objectstack` 111, `objectstack-ai/objectstack` 9, `Framework` 2. - Siblings: `objectui` 672, `cloud` 213, `hotcrm` 24, `objectstack-ai/objectui` 12, `ui` 11, `objectstack-ai/cloud` 9, `better-auth/better-auth` 3, `os-tianshun-mtc` 2, and 1 each of `hotcrm-heimao`, `os-project-titanwind-ehr`, `objectstack-ai/objectos`, `objectstack-ai/ats` and `objectstack-ai/hotcrm`. - Prose: `pre-` 284, `post-` 12, `Pre-` 4, `Post-` 4, `PRE-` 1 and `POST-` 1. - Ordinals: `OQ` 10, `PD` 8, `Prime-Directive-` 2, `PKCS` 1. - **`ui` is objectui.** `objectstack-ai/ui` does not exist, and `ui#6837`, `ui#6206` and `ui#6207` are objectui's records on its board (`objectstack#6206` answers 404, so it would have been a false death). - **Prose form, 27 sites.** For every objectui number I read objectui's board and this repository's. The objectui record is the one each sentence describes: `objectui objectstack-ai#2670` is "Flow designer: render loop / parallel / try_catch as nested", cited from `loop-node.ts`, and `objectui PR objectstack-ai#4264` diagnoses a path on the right side of `==`, cited beside `PATH_SHAPED_LITERAL`. This repository's same number is unrelated on every site. The `cloud` sites could not be read (private) and follow their context. There were zero false positives. - **Pair carry, 48 sites. The measurement refuses a carry rule.** - `,` and `and`: every cross-repo pair I could judge names THIS repository's second number. `cloud#1013 and objectstack-ai#10645` is this repository's cli `serve` issue (4 sites), `cloud#1020, objectstack-ai#5233` its org gate issue (6 sites), `objectui#2561, objectstack-ai#3021` its lazySchema PR, and `objectui#3136 and objectstack-ai#14492` answers 404 on objectui. - `/`: mostly carries, but not always. `objectui#3226 / objectstack-ai#4827` is this repository's objectstack-ai#4827, a conversion entry handed over from objectui and cited from `conversions/registry.ts`. - `+`: exactly one distinct pair exists in the corpus, which is too thin to establish a convention. ## Census of the newly judged spellings Taken with the gate's own `--census --json` at `a3c14755f8` against an enumerated board (184 pages, frontier objectstack-ai#20551). The per-site transition comes from the gate's `--list` before and after the change. Dead means `allocated-but-absent`. Four of the numbers (14657, 12998, 10194 and 8692) were re-probed directly and answered 404. | spelling | sites now judged | dead | |---|---:|---:| | `pre-#N` | 284 | 26 | | `framework#N` | 255 | 0 | | `post-#N` | 12 | 0 | | `Pre-#N` | 4 | 1 | | `Post-#N` | 4 | 0 | | `Framework#N` | 2 | 0 | | `PRE-#N` | 1 | 0 | | `POST-#N` | 1 | 0 | | **total** | **563** | **27** | Other readings, same run: - **Newly deferred (25 sites):** the 24 prose-form sites plus the respelled `field.zod.ts:370`. Four of them were base census deaths that were never deaths: `objectui PR objectstack-ai#8758` three times, and the respelled `objectstack-ai#6111`. - **No longer extracted (21 ordinals):** `OQ#10` ×10, `PD#12`/`PD#10` ×8, `Prime-Directive-objectstack-ai#10`/`objectstack-ai#12` ×2 and `PKCS#11` ×1. - **Whole-census tally:** - Base `288611e3e5`: 38,109 judged. resolves 32,202 · resolves-as-pull 1,863 · cross-repo-unjudged 1,535 · allocated-but-absent 2,509. - Branch `a3c14755f8`: 38,088 judged. resolves 32,689 · resolves-as-pull 1,891 · cross-repo-unjudged 976 · allocated-but-absent 2,532. - The board moved between the two runs, so the per-site transition above is the reading, not the tally difference. The cross-repo count reconciles exactly: 1,535 − 563 − 21 + 25 = 976. ## Verification All gates below ran at `a3c14755f8`, the branch head. - **Self-test.** `node scripts/check-issue-citations.mjs --self-test` exits 0 with 114 cases across 8 batteries (base: 73 cases across 7). The new battery `qualifier` (floor 40) pins every spelling both ways: lit on a live number and a FINDING on a dead one for `pre-` `post-` `Pre-` `Post-` `PRE-` `POST-`, and for `framework` `Framework` `objectstack-ai/framework` `objectstack`. It also pins cross-repo even when dead for `objectui` `OBJECTUI` `ui` `cloud` `hotcrm` `objectstack-ai/objectui` `better-auth/better-auth`, and covers: - an unknown word prefix read as prose; - the four ordinal heads; - the prose form, lit and dead, including `PR #N` and `UI #N` NOT being the prose form; - the pair, no carry (dead second number red) and qualified number by number (both deferred); - `boardWanted` and a probed-board resolution of `objectstack#20330`; - registry hygiene. `live-corpus` gains a pin that every qualifier the live corpus keeps names a repository. - **Ablations.** Six mutations went through `scripts/ablation-replace.mjs`, each landing on disk with the anchor count 1 → 0 and the blob changed, each red on its own case, and each restored with blob equal to HEAD `8b6cf12653dd` and `git diff HEAD` empty: - M1: the recogniser returns any bare candidate. The self-test reds on "`pre-` is prose". - M2: the probe set reverts to unqualified-only. It reds on "the board's probe set". - M3: the `framework` row is renamed. It reds on "`Framework` is THIS repository". - M4: the hyphen head is off. It reds on "`Prime-Directive-objectstack-ai#12`". - M5: the prose form is off. It reds on "`objectui PR #N` names objectui". - M6: the `OQ` head is removed. It reds on "`ADR-0076 OQ#10`". - **Diff-scoped verdict** (`node scripts/check-issue-citations.mjs`, as CI runs it): exit 0 on this branch. It judged the respelled line's 2 citations, both `cross-repo-unjudged`. - **One-time end-to-end proof** (no permanent test; injected uncommitted and restored with blob equal to HEAD and `git diff HEAD` empty). I appended `pre-objectstack-ai#12248` (dead) and `framework#20330` (live) to `packages/cli/src/commands/generate.ts` and ran the diff verdict twice: - The branch gate exits **2**. `pre-objectstack-ai#12248` is `allocated-but-absent`, `framework#20330` resolves on a board `probed (2 citations)`, and the respelled pair stays cross-repo. - The `288611e3e5` gate, from a temporary copy, exits **0** with all 4 `cross-repo-unjudged`. That is the hole this closes. - **Census** (`--census --json`): exit 0. It is report-only and never fails. - **Derived gates.** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 97 commands, and all 97 ran. 96 exit 0, including `pnpm check:pm-dispatch-gates`, whose `dispatch-gates.mjs --self-test` passes 1,976 cases. That self-test pins this file's `:204 local-env` declaration line, and every edit here stays below it or is line-neutral. `--ran` reconciliation reads "97 derived famil(ies) accounted for — 96 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)". - **NOT MEASURED: `check:dual-build-cjs-loads`.** Reason: it loads every package's built CJS entry, and this box holds no dist for 80+ packages. The diff changes no emitted code. `@objectstack/spec` was rebuilt, and its entry gates (`check:browser-reachable-entries`, `check:entry-nameability`) exit 0. CI's Lint and Repo Gates owns this one. - **Spec package.** `pnpm --filter @objectstack/spec typecheck` returned VERDICT command-exit 0. See the report comment for the test run. ## Acceptance notes - **Dead sites the census hands over, not rewritten here.** One is under `packages/spec/src/**` and is input for the staged sweep on objectstack-ai#20234: `packages/spec/src/meta-spelling/manifest-collection-spelling.ts:71` `pre-objectstack-ai#10194`. The other 26 are outside `packages/spec/src/**`, and no card names them: - `packages/cli/src/commands/generate.ts:1842` `pre-objectstack-ai#14657` - `packages/cli/src/utils/storage-driver.ts:206` `pre-objectstack-ai#6345` - `packages/drivers/driver-sql/src/schema-drift.ts:2458`, `:2474` `pre-objectstack-ai#12998` - `packages/drivers/driver-sql/src/sql-driver.ts:3872`, `:16545` `pre-objectstack-ai#17590` - `packages/drivers/driver-sql/src/sql-driver.ts:18285`, `:18324` `pre-objectstack-ai#12998` - `packages/drivers/driver-sql/src/sql-driver.ts:20095` `Pre-objectstack-ai#12380` - `packages/drivers/driver-turso/src/remote-transport.ts:2624` `pre-objectstack-ai#12380` - `packages/lint/src/validate-searchable-fields.ts:312` `pre-objectstack-ai#8404` - `packages/metadata-protocol/src/protocol.ts:2793` `pre-objectstack-ai#10888` - `packages/metadata-protocol/src/seed-loader.ts:1947` `pre-objectstack-ai#11674` - `packages/objectql/src/action-governance.ts:339` `pre-objectstack-ai#14423` - `packages/plugins/plugin-auth/src/auth-manager.ts:5629` `pre-objectstack-ai#14762` - `packages/plugins/plugin-security/src/bootstrap-platform-admin.ts:266`, `:630` `pre-objectstack-ai#8692` - `packages/plugins/plugin-security/src/per-organization-catalog.ts:314` `pre-objectstack-ai#8692` - `packages/plugins/plugin-security/src/permission-set-projection.ts:482` `pre-objectstack-ai#6483` - `packages/plugins/plugin-sharing/src/backfill-sys-record-share-organizations.ts:5` `pre-objectstack-ai#14484` - `packages/runtime/src/domains/mcp.ts:364` `pre-objectstack-ai#8726` - `packages/runtime/src/sandbox/body-runner.ts:548`, `:735` `pre-objectstack-ai#14758` - `packages/runtime/src/sandbox/script-runner.ts:440` `pre-objectstack-ai#14758` - `packages/types/src/driver-error-classification.ts:608` `pre-objectstack-ai#13324` - `packages/types/src/node.ts:1428` `pre-objectstack-ai#10943` - **The same `objectui#6110 + objectstack-ai#6111` pair outside the claim's surface.** It still reads `objectstack-ai#6111` as this repository's (404 here), so these are existing census deaths: `packages/spec/src/ui/view.zod.ts:3634` (for the objectstack-ai#20234 sweep), `packages/metadata-core/src/form-predicate-root-policy.ts:14`, `:120` and `:205`, and `packages/metadata/src/plugin.ts:910`. Each respells to `objectui#6110 + objectui#6111`. - **Pairs that read silently wrong, not dead.** Several `REPO#N / #M` pairs name the qualifier's own second number, which resolves here as an unrelated record. Examples: `hotcrm-heimao#35/objectstack-ai#40/objectstack-ai#59`, `objectui#2715/objectstack-ai#2717`, `objectui#2711/objectstack-ai#2722`, `objectui#4648/objectstack-ai#4901`, `objectui#5018 / objectstack-ai#6469`, `cloud#957 / objectstack-ai#962` and `cloud#930/objectstack-ai#944`. No gate can see these, because they resolve. The convention in the refusal text (qualify each number) is the remedy when someone next touches the line. - **Seat 4's `objectui PR objectstack-ai#10264` specimen.** `packages/spec/src/api/export-job-family-retirement.test.ts:25` sits on a DEFERRED surface (`packages/**/*.test.ts`), and `surfaceFor` answers `null` for it. The census never judged that site. The prose form it names is now read correctly wherever the census does look. - **Observed once: a truncated board enumeration accepted as a reading.** My first branch `--census` read `enumerated (126 pages)` with frontier objectstack-ai#13977, against 184 pages and objectstack-ai#20551 on the re-run minutes later, and reported 9,160 `never-issued` phantoms. `enumerateBoard` stops at the first page without `rel="next"` and trusts the maximum it saw as the frontier. This diff does not touch that code. The diff-scoped verdict enumerates only past 400 distinct numbers. Recorded, not filed; the seat decides. - **Scope declaration.** `NON_CITATION_HEADS` (two rows) and `nonCitationHead` (the hyphen) are grammar next to the qualifier, not the qualifier itself. They are here because closing the qualifier made those 13 ordinal sites judged citations of this repository's objectstack-ai#10, objectstack-ai#11 and objectstack-ai#12, which is false. No gate was added, and the diff-scoped blocking rule is unchanged. --- _Generated by [Claude Code](https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
veigajoao
pushed a commit
to veigajoao/objectstack
that referenced
this pull request
Sep 29, 2026
…mits that decided them (objectstack-ai#20626) Part of objectstack-ai#20596 Clause-②: no ## What changed This is the second stage of the `domain:services` lane of the dead-citation sweep. It covers `packages/plugins/plugin-sharing/src/**` and nothing else. By census, it is the largest package in the lane that no open PR or in-flight claim holds (the claim, `5886159115`, gives the order). Later stages cover the other packages, so this PR says `Part of` and the card stays open. Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123), by stage 1's method (PR objectstack-ai#20609, landed as `422db788a`). That is **87 sites on 86 lines in 23 files, covering 13 numbers**: the 60 census sites outside the generated headers, and 27 sites in test comments, which the census defers. Each rewritten line now cites the commit in `origin/main` history that decided what the line describes, and it says in its own words what that commit decided. No ADR or ruling-record file records the decision behind any of the 13 numbers (ADR-0131 names objectstack-ai#14484 only as evidence, not as the record of its ruling), so every anchor is a commit: **13 distinct shas**. No number was dropped. Only comments changed. Every touched source file keeps its line count (87 lines out, 87 in, over 23 files), so no line citation into these files moves. One of those 87 lines held no dead citation: `backfill-sys-record-share-organizations.ts:14`, where 「the cliff the card names」 lost its referent once line 10 named a commit instead of a card. It now reads 「the cliff that commit pins」, and `3f64fe6c6`'s backfill test is the one titled 「the cliff」. No code token moves (see the guard below). **No citation number is added.** Every tracker number on an added line was already on the line it replaces. Over the whole diff, added minus removed is 0 or negative for every number, and no number is new to the diff. No PR number stands on an added line. The one PR spelling in scope (`PR objectstack-ai#5973`, dead) became its squash commit. Nineteen dead sites are left on purpose: 1 string literal, 14 test titles, 1 verbatim ruling quotation and 3 generated file headers (see the list below). One more file: a `patch` changeset for `@objectstack/plugin-sharing`, because the rewritten docblocks ship (see Changeset below). ## Census: `plugin-sharing`, before and after **Instrument (A1).** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged. The count below is its `allocated-but-absent` findings under `packages/plugins/plugin-sharing/`. Each run counts as a reading only because its board frontier equals the newest issue number, read by a separate request just before and just after the run. | reading | tree | board | whole-repo `allocated-but-absent` | plugin-sharing sites | lines | files | numbers | |---|---|---|---|---|---|---|---| | before | base `422db788a`, run 2026-09-29T08:04:49Z to 08:08:19Z | enumerated, 185 pages, frontier objectstack-ai#20614 (newest objectstack-ai#20614), 18,441 numbers | 2,300 | **63** | 62 | 14 | 13 | | after | head `a6d231713`, run 08:27:44Z to 08:31:07Z | enumerated, 185 pages, frontier objectstack-ai#20616 (newest objectstack-ai#20616), 18,443 numbers | 2,240 | **3** | 3 | 3 | 1 | The before count matches the 63 that census `5884031174` read at `f11b5f20`. The whole-repo drop is 60, exactly this diff's census sites. The `resolves` tally is 32,803 in both runs, and `resolves-as-pull-request` (1,891) and `cross-repo-unjudged` (983) did not move either. The 3 left are the generated headers below. No run was truncated or discarded: all three enumerations in this stage (two census runs and the supplementary board below) read 185 pages at the newest frontier. **Supplementary instrument, the whole scope.** The census does not read test files or strings, and this stage's scope includes both. So a second reading runs the gate's own exported `extractCitations` (whole-file and comment-prose projections) and `classifyCitation` over every `.ts` file under `plugin-sharing/src` (74 files). It uses one board, enumerated by the gate's own `enumerateBoard` at 08:12:18Z (185 pages, frontier objectstack-ai#20614, equal to the newest). | reading | citations | dead | src comment | test comment | src string | test string | |---|---|---|---|---|---|---| | before, `422db788a` | 1,187 | **106** | 63 | 28 | 1 | 14 | | after, `a6d231713` | 1,100 | **19** | 3 | 1 | 1 | 14 | Its src-comment column equals the census's 63, which is the control on the second instrument. The 989 resolving, 87 pull-request and 5 cross-repo citations are the same in both readings. ## Per-number table Sites and files count all dead sites in scope at the base (comments and strings, tests included). `rewritten / left` counts the sites rewritten and the sites left. Each anchor was read in its message and diff, not only its subject. It is the commit that decided what the line describes: its own message or diff names the number it replaces, or, for a squash-merged PR, it is the merge of that PR. | number | sites / files | rewritten / left | anchor: what it decided | |---|---|---|---| | `objectstack-ai#5973` | 4/2 | 3/1 | `abeb3751f`: `HierarchyScopeContext.organizationId` is the tenancy authority, and it is required. `objectstack-ai#5973` was the PR itself; this is its squash commit | | `objectstack-ai#6206` | 12/7 | 11/1 | `8e13ca876`: the share-link routes hand enforcement the whole authz envelope, per maintainer ruling A of 2026-08-07. It is the plugin-sharing half; the spec stages anchor the contract half at `d7e0b4212`. Three sites name the ruling in words, 「the full-envelope ruling」, beside `aa4b90d9a`, which applied it | | `objectstack-ai#6523` | 3/3 | 3/0 | `aa4b90d9a`: 36 contract signatures converge on the full `ExecutionContext`. The same anchor the spec stages gave this number | | `objectstack-ai#8710` | 10/3 | 9/1 | `04d03c3a0`: a deactivated `sys_position` confers no sharing-rule shares. Its message quotes the 2026-08-15 ruling: access-conferring paths filter, addressing paths do not | | `objectstack-ai#8792` | 2/1 | 2/0 | `83c661d97`: the bulk-write merge's missing provenance mark is recorded as ruled (2026-08-15), not oversight | | `objectstack-ai#8836` | 1/1 | 1/0 | `1850ebbb0`: it pins 「no filter object that can be vouched 'author' may outlive the request that vouched it」, the invariant the line names. The same anchor the spec stages gave this number | | `objectstack-ai#11671` | 5/5 | 2/3 | `09b4f4e4e`: `os i18n extract --source-hashes` writes the provenance companion (maintainer ruling objectstack-ai#12069 Option A, which stays cited). The same anchor stage 1 gave it | | `objectstack-ai#11674` | 4/2 | 4/0 | `1cba33f16`: the seed loader warns at load time when a required column is deferred, and the ordering constraint is written at the four pointer-pair sites, these two among them | | `objectstack-ai#12493` | 2/2 | 2/0 | `aa5994e17`: the Operation Message Catalog gains `record_write_denied` ahead of its emitters. The same anchor the spec stages gave this number | | `objectstack-ai#13279` | 3/2 | 3/0 | `6a180e42d`: a permission-store read that throws raises `AuthzStoreUnavailableError` (503), and each transport re-raises it rather than laundering it into a 401 | | `objectstack-ai#13398` | 1/1 | 1/0 | `953a81f4a`: the class ruling on published logger sinks, applied at this site. `error` is reachable only because the sink already declares it; growing `error?` onto a published sink is forbidden. No record of the ruling exists in the repo, and this commit, which wrote this heading, is its earliest application in history | | `objectstack-ai#13608` | 23/3 | 21/2 | `fc9ba76a5`: `publicSharing.eligibility` is held at redemption, not only at mint. The same anchor the spec stages gave this number | | `objectstack-ai#14484` | 36/8 | 25/11 | `3f64fe6c6`: `organization_id` is stamped on every `sys_record_share` write, the stranded rows are backfilled, and the object is admitted to the tenancy ledger (the 2026-09-02 ruling, decision batch objectstack-ai#11 item 3) | Every cited sha matches exactly one commit (`git rev-parse --disambiguate`, count 1 for each), and every one is an ancestor of the base (`merge-base --is-ancestor`, exit 0 for all 13). The history is complete (`--is-shallow-repository` false, 15,073 commits). A line-origin pickaxe (`git log -S` on each dead line's exact text) found each line entering either in its anchor commit or in a later commit that cites that commit's decision. For example, `65759baca` is the consumer half that cites `aa5994e17`'s key, and `b70a55d62` cites `3f64fe6c6`'s ledger admission. Wordings to check, each true of its commit: - `backfill-sys-record-share-organizations.ts:5`: 「rows that `SharingService.grant`, before commit 3f64fe6, stranded」. `3f64fe6c6` is the writer fix, and this module is its backfill. - `backfill-sys-record-share-organizations.ts:36` and `:124`: 「the 2026-09-02 ruling commit 3f64fe6 applies (decision batch objectstack-ai#11 item 3, …)」. The verbatim maintainer quotation on line 37 is untouched. - `share-link-service.ts:841`: 「(published-sink level ruling, commit 953a81f)」. The heading's body already states the ruling (option C allowed, option B forbidden). - `exec-context-annotation.pin.ts:7-8`, `sharing-rule-service.ts:12-13` and `sharing-service.ts:20`: 「since commit aa4b90d (the full-envelope ruling: no per-site subset contracts)」. `aa4b90d9a`'s message: 「Apply the … ruling default (converge on the full envelope, keep no per-site subset contracts)」. - `share-link-routes.ts:81`: 「[commit 8e13ca8, full-envelope ruling]」, so that 「the whole point of the ruling」 five lines down still has a referent. ## The 19 sites left - **Non-test string (1 site).** `sharing-service.ts:1674` sits inside the operator-facing `warn` text for a hierarchy scope that was not widened (「… resolveOwnerIds, objectstack-ai#5973); …」). It is a runtime string, so it is form D, not form C, and the shrink-only `doc-authoring-prose-id` baseline already holds it (`sharing-service.ts` → `objectstack-ai#5973: 1`). Left and listed, as stage 1 left its refusal strings. - **Test titles (14 sites).** `describe` titles in `backfill-sys-record-share-organizations.test.ts:185`, `:274`, `:324`, `:367`, `record-share-organization-stamp.test.ts:194`, `:239`, `:278`, `:315`, `:353`, `:436`, `sharing-service.test.ts:1798` (the `objectstack-ai#14484` titles), `share-link-eligibility.test.ts:607` (`objectstack-ai#13608`), `share-link-enforcement-context.test.ts:226` (`objectstack-ai#6206`) and `sharing-rule.test.ts:1898` (`objectstack-ai#8710`). Tokens, left as they were. - **A verbatim ruling quotation (1 site).** `share-link-service.test.ts:478` is point 2 of the maintainer's 2026-09-01 ruling, quoted verbatim and untranslated. It carries 「沿 objectstack-ai#13608 先例」. AGENTS.md keeps a quoted Chinese ruling in its original words, and rewriting the quote would rewrite the ruling. Left. - **Generated headers (3 sites).** Line 8 of the `es-ES`, `ja-JP` and `zh-CN` `.source-hashes.generated.ts` files carries 「(objectstack-ai#11671, maintainer ruling objectstack-ai#12069 Option A, extending objectstack-ai#8765 Option B)」. `os i18n extract` writes that line from `packages/cli/src/utils/i18n-extract.ts`, so the fix belongs at the producer, the carrier stage 1 named. The hand-written `translations/index.ts:26` is rewritten here, with the same wording stage 1 used. ## Mechanical guard: no code token moves The guard compares the TypeScript parser's leaf nodes, with comments as trivia and JSDoc nodes excluded, base `422db788a` against head. Template literals are therefore read in context. It ran over all 23 touched `.ts` files. - Real run: 96,665 base tokens, **0 files with a token change** (exit 0). - Comment-insertion control in `share-link-service.ts`: 0 files changed, as expected (exit 0). The first attempt was a no-op: its replacement still contained the anchor, so `scripts/ablation-replace.mjs` refused it before the guard ran. It was redone with an anchor the replacement does not contain. - Positive control, a code token changed in `share-link-service.ts` (`Boolean(eligibility),` to `Boolean(eligibility) && true,`): DIFFER (exit 1). - Positive control, one digit changed inside the kept `sharing-service.ts:1674` warn string: DIFFER (exit 1). Every mutation went through `scripts/ablation-replace.mjs`. Each restore was proven byte-identical to the HEAD blob (`ba7fba2e8199`, `2833b9a1616d`), with `git diff HEAD` empty and a clean tree afterwards. ## Changeset This change ships bytes, so a `patch` changeset for `@objectstack/plugin-sharing` is included. It says only that the provenance comments were re-anchored. Measured on the built package (A3): `files[]` is `dist`, `README.md` and `CHANGELOG.md`. After the build, the rewritten comments reach both halves of `dist`: `3f64fe6c6` appears 6 times in `dist/index.d.ts` and 8 in `dist/index.js`, `fc9ba76a5` 3 and 3, `04d03c3a0` 2 and 2, `8e13ca876` twice in `index.d.ts`, and `1cba33f16` 4 times in `index.js`. esbuild keeps only some comments, so the positive controls are unchanged lines beside rewritten ones that shipped. `share-link-service.ts:891` is found once in each half, and `sharing-service.ts:1269` once in `index.js`. A never-written negative phrase appears nowhere. The only dead number left in `dist` is the kept `objectstack-ai#5973` warn string. ## Gates (head `a6d231713`) - **Citation judging, as CI runs it:** `pnpm check:issue-citations` (self-test) exits 0. `node scripts/check-issue-citations.mjs` exits 0: the diff-scoped run judged 9 citations across 11 files, and all 9 resolve. - **Doc authoring:** `pnpm check:doc-authoring` exits 0, with the sibling-package prose ids at their baseline and no growth. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `a6d231713` (re-derived after a fresh `git fetch` at 09:58Z: the same 65, and none of the 8 new `main` commits touch anything it derives from) derived 65 commands. They include all 50 derived at dispatch, plus 15 more. All 65 exit 0. `--ran` reports 65 run, 0 NOT MEASURED, 0 unrun, and exits 0. - Three gates first exited 3 (PREREQUISITE NOT MET) because the workspace was only partly built: `check:dual-build-cjs-loads`, `check:i18n` and `check:type-check-debt`. A full `turbo run build` of `./packages/*` and `./packages/*/*` then ran under the shared verify lock (71 tasks, exit 0), and all three exited 0 on their rerun. `check:dts-closure`, `check:sourcemap-no-sources-content` and `check:lean-entry-closure` were rerun too, over 71, 68 and 15 built packages, and exited 0. - **Tests and typecheck, under the verify lock:** - `pnpm --filter @objectstack/plugin-sharing test`: 37 files and 913 tests pass. That is every test file in the package, the 12 touched ones included. - `pnpm --filter @objectstack/plugin-sharing typecheck` exits 0. Its main `tsc` program reads the 37 non-test files, and its `check:test-typecheck` program (`tsconfig.test.json`) reads all 74 files under `src/`, the 37 test files included (`--listFiles`). - **Lint, as a proven narrowing:** `eslint --no-inline-config --format json` over the 23 touched `.ts` files gives 23 files, 0 errors and 0 warnings. All 23 are in eslint's own population (`isPathIgnored` is false for each). `eslint.config.mjs` never enables type-aware linting (no `parserOptions.project`, as its own line 328 states), so a comment edit here cannot move the verdict on any untouched file. The repo-wide `pnpm lint` is CI's run. - **Control bytes:** `pnpm check:nul-bytes` exits 0, and a raw scan of the 24 changed files for control bytes finds none. ## Acceptance notes - **The census instrument did not truncate in this stage.** Three enumerations read 185 pages each at the newest frontier. The truncation stage 1 saw (1 run in 5) is carried on objectstack-ai#20556, and this stage changes no instrument. - **What stays for later stages.** - The 3 generated `objectstack-ai#11671` headers, whose producer is `packages/cli/src/utils/i18n-extract.ts`. - The `objectstack-ai#5973` warn string (form D, held by the `doc-authoring-prose-id` baseline), the 14 test titles and the verbatim ruling quotation. - **Anchors the next stages can reuse.** The same numbers stand elsewhere in `packages/**/src`: `objectstack-ai#6206` at 53 sites and `objectstack-ai#11674` at 46 (the ordering-constraint note has two sibling copies outside this package, in `sys-approval-request.object.ts` and `sys-audit-log.object.ts`). `8e13ca876` / `d7e0b4212` / `aa4b90d9a` and `1cba33f16` are the anchors used here. - **Base.** The branch is 8 commits behind `origin/main` (`1322cc72c`, read at 09:58Z). None of them touches `plugin-sharing` or this changeset, and none re-anchors any of these 13 numbers, so there was no merge. --- _Generated by [Claude Code](https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 2, 2026
This branch had an error being deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Replace the custom
@objectdocs/clidocumentation tooling with Fumadocs, a modern Next.js-based documentation framework, and restructure it into a proper monorepo architecture underapps/docs/while keeping documentation content at the root level for sharing.Changes
Monorepo Structure
apps/docs/to avoid polluting the root directorypackage.jsonwith isolated dependenciespackages/*) and applications (apps/*)/content/docs/(root level) for easy access and sharing across the repositoryCore Infrastructure
/content/docs/(root level) with type-safe collection handling@tailwindcss/postcssDirectory Structure
Configuration
UI Components
fumadocs-ui/mdxBuild Output
Workspace Configuration
pnpm-workspace.yamlto includeapps/*package.jsonscripts use workspace filters:pnpm --filter @objectstack/docspackage.jsonincludes shared dependencies (lucide-react) used by MDX filestsconfig.jsonexcludes apps directory.gitignoreupdated for apps structureScreenshot
Scripts
Scripts remain the same from repository root:
Benefits
/content/docs/accessible to other tools and workflowsapps/playground,apps/studio)All existing MDX content preserved at the root level. The
.source/directory (auto-generated by Fumadocs) is gitignored.Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.