Skip to content

Commit 7d37f24

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-6243-description-truth-sweep
2 parents a00bdbb + 95c4227 commit 7d37f24

180 files changed

Lines changed: 2423 additions & 2509 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
fix(spec): docs-gen renders a module description as the markdown it was written as (#5553, #6136)
6+
7+
Two independent defects in `scripts/lib/file-description.ts`, both from a
8+
transform applied at the wrong granularity. The block SELECTION rule #5059 added
9+
is untouched: all 185 sources that carried a module header still render one, and
10+
no page gained or lost an opening paragraph.
11+
12+
**#5553 — line layout is content, not decoration.** The renderer dropped every
13+
blank line and joined what survived with `\n\n`, making each SOURCE LINE its own
14+
paragraph. Anything that legitimately wraps across lines was then cut in half by
15+
a paragraph boundary, and an inline code span cannot cross one, so both of its
16+
backticks fell out as literal text — `` `explain(principal, object, `` /
17+
`` operation)` `` on `security/explain`, and three more like it. The same pass
18+
escaped `{` and `}` everywhere including inside code, where a backslash is not
19+
an escape character but a character the reader sees, so pages published
20+
`` `\{ dialect, source \}` ``.
21+
22+
The fix is to stop rewriting the layout: strip the ` * ` gutter and keep the
23+
lines as authored. Markdown's own rules then do what the issue asked for —
24+
consecutive lines are one paragraph, a blank line opens the next — and lists,
25+
headings, tables and code blocks keep working, which the literal space-join the
26+
issue floated would have broken on the 85 sources that write a list. Escaping and
27+
link resolution are now scoped to prose: fenced and indented code blocks are
28+
copied verbatim, and within prose a tokenizer keeps inline code spans out of
29+
reach.
30+
31+
One construct is deliberately NOT reproduced as authored: an indented (4-space)
32+
code block is re-emitted as a fenced one. MDX dropped CommonMark's indented code
33+
blocks so that indentation could lay out JSX, so such a block reaches the MDX
34+
compiler as ordinary prose — and unescaped braces in prose are an expression.
35+
`data/date-macros` and `data/context-tokens` write their placeholder examples
36+
that way and are almost entirely braces; left indented they fail to compile
37+
("Could not parse expression with acorn"), and escaped instead they show `\{` in
38+
what is meant to be code. The target dialect has one spelling for a code block.
39+
40+
Measured over the 185 rendered descriptions: paragraphs with unpaired backticks
41+
8 → 0 (`automation/flow-function`, `security/explain`, `shared/expression`,
42+
`system/settings-client`), and backslash-brace residue inside code 296 → 0 across
43+
33 pages. 32 pages get their fenced `@example` sample back as a real code block
44+
instead of one escaped paragraph per line, and 47 regain the indentation that
45+
made a nested list nested. The issue named five victim pages; `system/doc` is not
46+
among them because #5059 has since found its header documents `DocSchema` and
47+
stopped publishing it.
48+
49+
**#6136 — a rewriter that ran over its own output.** The untitled
50+
`{@link <path>}` branch emits `[<path>](<route>)`, whose link TEXT is the path
51+
itself. The bare-source-path rewriter ran next over the whole string and matched
52+
that text, wrapping it a second time into a link nested in a link. Lookaround
53+
cannot express "not nested inside a link", so the rewriter is now applied per
54+
prose token with formed links excluded. `automation/etl` and
55+
`integration/connector` each get their "See also" back as one clickable link.
56+
57+
169 reference pages are regenerated. No runtime, package export or protocol
58+
semantics change — this is the docs generator only.

.changeset/lucky-moons-smoke.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@objectstack/metadata-protocol': patch
3+
'@objectstack/objectql': patch
4+
---
5+
6+
fix(metadata-protocol): boot 重水合按行的真实 package 绑定登记对象归属(#4636 裁 B 收官)
7+
8+
`loadMetaFromDb` 的 object 分支从 `engine.find` 返回的行上读 `record.packageId`,而 `sys_metadata` 的列是 snake_case 的 `package_id` —— 该表达式恒为 `undefined || 'sys_metadata'`,于是每次重启都把**绑定了包**的对象 overlay 登记在 `'sys_metadata'` 哨兵下。改为读 `package_id`,与写路径、`getMetaItems`、以及相邻的非 object 分支一致。
9+
10+
用户可见的行为差异:归属键同时就是包过滤键(`getAllObjects(packageId)`),所以此前一个对象在**创建时**出现在自己所属包的侧边栏过滤里,**重启之后就消失**;更要紧的是重启后的第一次编辑——boot 登记 `'sys_metadata'`、保存登记 `app.<slug>`,`registerObject``already owned by package …``applyObjectRegistryMutation` 吞成 `console.warn`,保存回 `success: true` 而内存 schema 停在重启时的版本,这一笔编辑被静默丢弃(cloud#970 的重启面)。两侧统一到真实 id 后,过滤与编辑都跨重启成立。
11+
12+
`@objectstack/objectql` 仅同步 `registry.ts``isTenantAuthored` 的契约注释:PR1 标注的「这半句描述的是契约,还不是代码」随本次落地摘除。

.github/workflows/lint.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,27 @@ jobs:
717717
- name: Check the decision frame is in sync across its four copies
718718
run: pnpm check:skill-frame-sync
719719

720+
# The third gate over SKILL.md, covering the one line the other two cannot see
721+
# (#5331). check:skill-docs / check:skill-refs compare generated artifacts and
722+
# check:skill-examples typechecks `os:check` blocks; none of them reads the
723+
# `compatibility:` frontmatter line. That blind spot is measured, not theoretical:
724+
# nine of ten skills declared `@objectstack/spec 16.x` for an entire major cycle
725+
# while teaching 17's capabilities, with all three gates green throughout (#5245).
726+
# #5245 corrected the values by hand; this reconciles them against
727+
# packages/spec/package.json on every run so they cannot drift again.
728+
#
729+
# Note the contract is the wording that actually LANDED for #5245 — an exact
730+
# `<major>.x` pin. If the wording is ever changed to an unpinned range, this gate
731+
# goes RED rather than quietly matching nothing (#4690): a gate that cannot find
732+
# its input must fail, never skip.
733+
#
734+
# Same job and same reasons as its neighbours: no paths filter and required, so it
735+
# cannot go dormant on exactly the PR that breaks it — and a `skills/**` filter in
736+
# particular would blind it to the other half of its input, packages/*/package.json,
737+
# where a major bump is what makes the declarations stale in the first place.
738+
- name: Check SKILL.md compatibility declarations match the workspace majors
739+
run: pnpm check:skill-compatibility
740+
720741
- name: Check the react-blocks contract is in sync with the spec
721742
run: pnpm --filter @objectstack/spec check:react-blocks
722743

AGENTS.md

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -190,20 +190,87 @@ Even inside your own worktree, operate defensively:
190190
your working-tree change between the edit and the commit. On a real conflict,
191191
re-apply only *your* lines and let the PR merge integrate the rest.
192192
6. **Don't rebase or force-update shared branches** to tidy other agents' commits.
193-
7. **Merge only after remote CI is fully green. Never `gh pr merge --auto`.**
194-
Auto-merge can land a still-red PR onto shared `main` and break it for every
195-
parallel agent (see #1475). Merge serially; rebase other open branches before
196-
merging the next one.
197-
**Once the repo's merge queue is enabled, "add to queue" IS the sanctioned
198-
path** — it is the opposite of the auto-merge this rule bans: the queue
199-
builds your PR *as merged onto the current `main`* and lands it only if that
200-
speculative result is green, which is exactly the §10 re-verification, done
201-
by the platform, race-free. The manual serial protocol above is the fallback
202-
for when the queue is unavailable. (Why this matters: `main` can land a PR
203-
every few minutes at peak; a manual merge–reverify loop takes ~25 minutes,
204-
so under load it *never* wins the race — one PR went three full green
205-
cycles without managing to land. That is a livelock, not a discipline
206-
failure.)
193+
7. **Land through the merge queue: arm auto-merge on a PR that is already
194+
green, accepted and non-draft, then let the queue merge it.** Arming is how
195+
you enter the queue, and the queue is what makes arming safe — it rebuilds
196+
your PR *as merged onto the current `main`*, re-runs the subscribing
197+
workflows on that rebuilt generation, and lands it only if the required ones
198+
pass. That is the §10 re-verification, done by the platform, race-free.
199+
200+
**What "the queue validates" means here, measured** (`origin/main`,
201+
2026-08-07): three of this repo's 22 workflows carry an `on: merge_group:`
202+
trigger — `ci.yml`, `lint.yml`, `spec-liveness-check.yml` — and the Actions
203+
API reports **2742** `merge_group` runs, the most recent 30 all on
204+
`gh-readonly-queue/main/pr-<n>-<sha>` refs, all three workflows, all green.
205+
A fourth workflow, `merge-queue-triage.yml`, is *not* a subscriber: it
206+
watches those runs through `workflow_run` and comments the diagnosis on the
207+
PR when a queue build goes red (#4859).
208+
209+
**This supersedes the older "never `gh pr merge --auto`" ban.** Its premise —
210+
auto-merge lands a still-red PR on shared `main` (#1475) — is inverted by
211+
rebuild-then-land, and the ban forbade what is now the sanctioned path. Its
212+
*true half* survives, as a precondition rather than a prohibition: **arm only
213+
what is already green and accepted**, where green means the gate-carrying
214+
jobs' `conclusion` is `success`, not "no failure yet" — `in_progress` is not
215+
a pass. Arming a red PR does not queue it, it hides it: #4852 sat armed from
216+
10:15 for **100 minutes** without ever entering the queue, every poll
217+
misreading "not on `main` yet" as "queued". So always read *two* things when
218+
checking on a landing: the queue branch **and** `origin/main`.
219+
220+
**The queue enforces only the required set; everything else is advisory and
221+
rides through.** #6067's final queue generation
222+
(`gh-readonly-queue/main/pr-6067-db0d53c2…`) had `Lint & Type Check` at
223+
`completed/failure` — run 31136745851, concluded 01:12:11Z — and merged at
224+
01:13Z regardless; the `check:slot-lookup` red it carried then rode `main`'s
225+
merge ref into every following PR's ESLint job until it was stanched (#6100,
226+
the same shape as #5584#5601 → hot-fix #5615). Governance half: **#5617**,
227+
under which the maintainer on 2026-08-07 added **ESLint** and **TypeScript
228+
Type Check** to both `main`'s required-status-check set and the queue's check
229+
set, so those two now block — the audit archived on that issue also lists
230+
which other jobs can and cannot safely join them. A gate outside that set
231+
stops nothing, which is why "arm only on green" is a rule and not a
232+
formality.
233+
234+
**Three re-arm situations this repo has actually hit.** None of them is a
235+
reason to avoid the queue; all are reasons to confirm a PR is still *in* it:
236+
- **A red queue build ejects your entry and drops the auto-merge.** The
237+
failure is often in a package your PR never touched, because the queue runs
238+
the *full* suite while the PR ran affected-only. #6059 was ejected at
239+
01:03:02Z on a known flaky (`datasource-pool-support.test.ts`, #6044),
240+
diagnosed against the triage comment, re-armed at 01:04:15Z and landed at
241+
01:25:00Z. Recognise the signature first, then re-arm once — never re-queue
242+
reflexively.
243+
- **Collateral eviction is silent by design.** `merge-queue-triage.yml`
244+
comments only on `conclusion == failure`; an entry cancelled because
245+
something *ahead* of it failed gets nothing, since that outcome says
246+
nothing about your PR. A PR that is neither on `main` nor in the queue was
247+
dropped — re-arm it.
248+
- **Flipping back to draft drops auto-merge and queue membership at once, and
249+
neither returns by itself.** The order is therefore fixed: ready *first*,
250+
arm *second*. (This one is the repo's standing operating note —
251+
`.claude/skills/pm-dispatch/SKILL.md` note 1 — not an API measurement.)
252+
253+
And one non-fix: **a stale red does not clear by re-running.**
254+
`rerun_failed_jobs` reuses the original run's commit and merge ref, so it
255+
cannot see a fix that landed on `main` since. Compare the fix's merge time
256+
against the run's creation time; if the fix is later, only a new commit
257+
(`git merge origin/main`) helps — #4852's red was byte-identical across a
258+
rerun until #4856 landed.
259+
260+
**Not measured here:** whether a direct, non-auto `gh pr merge` is refused
261+
with `405 Changes must be made through the merge queue`. Establishing that
262+
would mean actually attempting a merge on a live PR, which is not an
263+
experiment worth running. objectui returns 405; that is **not** extrapolated
264+
to this repo (objectui#3243) — separate rulesets, and #5617's cross-repo
265+
audit found the two configured differently.
266+
267+
**Fallback, when the queue is unavailable:** the old manual protocol — merge
268+
serially, only after remote CI is fully green, rebasing other open branches
269+
before merging the next one. It is a fallback because it loses under load:
270+
`main` can land a PR every few minutes at peak while a manual merge–reverify
271+
loop takes ~25 minutes, so one PR went three full green cycles without
272+
managing to land. That is a livelock, not a discipline failure — and it is
273+
why the queue is the default path rather than an optimisation.
207274
8. **Testing needs a server? Start your own temporary one — never stop someone
208275
else's.** A running dev server you didn't start probably belongs to another
209276
agent or the user; killing it (or its port) breaks their in-flight work. Spin
@@ -253,8 +320,9 @@ Even inside your own worktree, operate defensively:
253320
- **Full `pnpm typecheck && pnpm test` again only when** the incoming
254321
commits touch the same packages or the same behavior your diff does, or a
255322
conflict occurred outside trivially-mechanical files.
256-
- CI on the PR (and the merge queue, once enabled) validates the merge
257-
commit itself — that second CI round is where joint breakage surfaces, and
323+
- CI on the PR, and then the merge queue on its rebuilt generation (§7),
324+
validates the merge commit itself — that second CI round is where joint
325+
breakage surfaces, and
258326
the guards in `scripts/check-*.mjs` exist largely because this class of
259327
breakage is invisible to `git merge`.
260328
11. **Generated artifacts don't text-merge — a driver defers them and
@@ -765,10 +833,10 @@ it to `OPEN_CAPABILITY_REGISTRIES` in the same PR that fixes it.
765833

766834
1. `pnpm test` — verify nothing broke. Touched a type-check-covered package? `pnpm typecheck` too.
767835
2. **Land it — don't leave passing work in the working tree.** Once tests pass,
768-
create a feature branch, commit, push, open a PR, and merge it after remote
769-
CI is fully green (see Multi-agent discipline: never straight to `main`,
770-
never `gh pr merge --auto`). A finished task = a merged PR, not a dirty
771-
working tree.
836+
create a feature branch, commit, push, open a PR, and — once remote CI is
837+
fully green and the PR is accepted — arm auto-merge so the queue lands it
838+
(Multi-agent discipline §7: never straight to `main`; never arm a PR that
839+
isn't green yet). A finished task = a merged PR, not a dirty working tree.
772840
3. **Add a changeset for feature work.** When the change is a feature or functional improvement, run `pnpm changeset` (or add a `.changeset/*.md` entry) describing it before committing. Pure bug fixes do **not** require a changeset.
773841
**Breaking changesets must carry their migration.** If the change removes or renames anything an author can write (a spec key, an export, a config field), the changeset body must state the FROM → TO mapping and the one-line fix — this text ships to consumers as `CHANGELOG.md` inside the npm package and is what an upgrading agent greps after the tombstone error. Removing an authorable spec key also requires a tombstone so the rejection itself carries the prescription — `retiredKey()` (`packages/spec/src/shared/retired-key.ts`) on a non-strict schema, or an entry in the relevant `UNKNOWN_KEY_GUIDANCE` / `*_RETIRED_KEY_GUIDANCE` map (see `object.zod.ts`, `ai/tool.zod.ts`) when the schema is `.strict()`. The changeset is one of fourteen surfaces a retirement touches — follow the `spec-property-retirement` skill (`.claude/skills/`) rather than reconstructing the kit, and note the two routes imply **opposite** liveness-ledger dispositions.
774842
4. **Added or removed a `packages/spec` export? Run `pnpm --filter @objectstack/spec gen:api-surface` and commit the result.** The `TypeScript Type Check` job diffs spec's built export surface against `api-surface/` (one shard per entry point since #5837); a new export makes the snapshot stale and turns the job red. It reads the **built `dist` declarations**, so `OS_SKIP_DTS=1` — the flag you reach for to make local builds fast — skips exactly the artifact the gate inspects, and the check passes locally while failing in CI. Same shape for the other generated-artifact gates in that job (`check:docs`, `check:skill-refs`, `check:react-blocks`), which read `src/` and so do reproduce locally.

content/docs/references/ai/conversation.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ description: Conversation protocol schemas
88
AI Conversation Memory Protocol
99

1010
Multi-turn AI conversations with token budget management.
11-
1211
Enables context preservation, conversation history, and token optimization.
1312

1413
<Callout type="info">

content/docs/references/ai/embedding.mdx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,17 @@ Embedding & Vector Store Primitives
1010
Platform contract for configuring embedding models and vector stores.
1111

1212
Scope (intentionally minimal):
13-
1413
- How to reference an embedding model (provider + model name + secret).
15-
1614
- How to reference a vector store (provider + connection).
1715

1816
NOT in scope (these belong to application code, not the platform):
19-
2017
- Chunking strategies (fixed/semantic/recursive/markdown).
21-
2218
- Retrieval pipelines (rerankers, multi-stage retrieval, filters).
23-
2419
- Document loaders / ingestion DSLs.
25-
2620
- End-to-end RAG pipeline orchestration.
2721

2822
These were removed in v1 because they describe one specific way to
29-
3023
build a RAG application; the platform's job is to expose the embed +
31-
3224
vector primitives so any RAG strategy can be built on top.
3325

3426
<Callout type="info">

content/docs/references/ai/knowledge-document.mdx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@ description: Knowledge Document protocol schemas
66
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
77

88
Knowledge Document / Chunk / Hit — canonical shapes shared by every
9-
109
`IKnowledgeAdapter` implementation.
1110

1211
The framework does **not** prescribe chunk strategy or vector
13-
1412
format. Adapters are free to chunk however they like; the framework
15-
1613
only requires they round-trip these shapes when talking to the
17-
1814
`IKnowledgeService`.
1915

2016
See `content/docs/protocol/knowledge.mdx` for the full design.

content/docs/references/ai/knowledge-source.mdx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,12 @@ description: Knowledge Source protocol schemas
66
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
77

88
Knowledge Source — declarative metadata describing what to index and
9-
109
which adapter to use.
1110

1211
A KnowledgeSource is the metadata-level equivalent of an
13-
1412
`IDataEngine` driver binding: it pairs a logical source description
15-
1613
(object/file/http) with the *id* of an `IKnowledgeAdapter` plugin
17-
1814
that will actually do the work. The adapter resolves the id at
19-
2015
runtime via `IKnowledgeService.registerAdapter`.
2116

2217
See `content/docs/protocol/knowledge.mdx` for the full design.

0 commit comments

Comments
 (0)