Skip to content

Commit 92d0b6d

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-13801-duration-unit-declaration
2 parents c1e4ca8 + 9c7d9d4 commit 92d0b6d

44 files changed

Lines changed: 1701 additions & 714 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
"@objectstack/objectql": patch
3+
---
4+
5+
fix(objectql): decide the insert-side runtime-owned strip by hook-write PROVENANCE, not `Object.is` (#14259)
6+
7+
#14088 replaced `Object.is(payload[k], supplied[k])` inside `stripReadonlyFields`
8+
with a recording of the keys the before-phase hook chain actually assigned
9+
(`recordHookPayloadWrites`). Its argument was never about `null`: value equality
10+
cannot separate *the hook deliberately wrote the value the caller also sent* from
11+
*the hook never touched the key*, and those two demand opposite verdicts.
12+
13+
`stripRuntimeOwnedFields` — the INSERT-side twin — was left on the comparison
14+
that argument retired, and #6339's own prose is the finding: it argued a key SET
15+
made the contract true "only BY ACCIDENT" and moved to values, which is
16+
accidental in the identical way. A `beforeInsert` hook that re-issues or
17+
normalises a record number therefore still lost its write to any caller that
18+
submitted the same value — the caller who omitted the key kept the hook's number,
19+
the caller who echoed it got the sequence value, and the two differed in nothing
20+
else.
21+
22+
`engine.insert` now arms one recording **per row** at hook-context construction
23+
and seals each immediately after that row's `beforeInsert` chain, and
24+
`stripRuntimeOwnedFields` consults the sealed record before the value test. Per
25+
row, never per call, so a hook stamping one row of a batch confers nothing on the
26+
next.
27+
28+
**Not a relaxation of #5503, and the accept set for callers does not move.** A
29+
caller-seeded record number that no hook assigned is still stripped, still warns
30+
with the same text, and still reports through `onFieldsDropped` /
31+
`strictReadonlyWrites`; `isSystem` and `preserveAudit` are untouched. What
32+
changed is only the EVIDENCE for the hook-write exemption that already existed —
33+
a record of which keys were assigned, instead of an inference from the values
34+
afterwards.
35+
36+
The forgery boundary is inherited verbatim: a caller-supplied value must never
37+
become hook-owned. The new insert-side recording is armed after the caller's
38+
payload has arrived and been snapshotted, sealed before any engine-owned pass
39+
touches the row, and records that an assignment ran rather than anything about
40+
the payload's contents — a caller cannot execute an assignment, so no key it
41+
sends can enter the record. A hook that REPLACES the payload object leaves no
42+
attributable record and falls back to the pre-existing value test, which
43+
over-strips: keeping the old bug is the only safe direction, because reading a
44+
replacement's keys as hook-owned would launder a caller's forgery.
45+
46+
The `readonlyWhen` sibling seam #14259 also names (`isCallerSuppliedValue`,
47+
behind `stripReadonlyWhenFields` / `stripReadonlyWhenFieldsMulti`) is **not**
48+
included: threading the record there was measured to let a caller's value survive
49+
a TRUE `readonlyWhen` predicate, which is a maintainer decision rather than a
50+
mechanical follow-through. Nothing about that seam's behaviour changes here.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
Reference pages no longer open with the `@module` marker line. That tag is what
6+
tells the docs generator which doc block describes the module, but it is
7+
machinery for the selector, not prose — and the renderer emitted it verbatim, so
8+
fourteen published pages opened on the literal text `@module ui/sharing` instead
9+
of on their first sentence. `renderFileDescription` now drops the marker at prose
10+
level, exactly as it already drops the `check:skill-examples` opt-in marker, and
11+
as the skill-index extractor has always done. The marker stays in the source and
12+
still selects the block; only `@module` is dropped, because `@example` and
13+
`@category` carry prose a line-drop would take off the page. No schema behavior
14+
changes.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
"@objectstack/objectql": patch
3+
"@objectstack/runtime": patch
4+
---
5+
6+
fix(objectql): `SchemaRegistry.registerObject`'s cross-package ownership refusal carries an ADR-0112 envelope (#14367)
7+
8+
The ADR-0029 D3 refusal — a package claiming `own` on an object name a DIFFERENT package already owns — was a bare `Error`: no `code`, no `status`. It is now `ObjectOwnershipConflictError` with `code: 'OBJECT_OWNERSHIP_CONFLICT'` and `status: 422`, plus `objectName` / `existingPackageId` / `incomingPackageId` as fields, the same shape as the sibling `ArtifactObjectNameConflictError`. The message text is byte-for-byte unchanged, so every message-substring assertion and every forwarder that interpolates it (`console.warn`, the per-record `errors` count) reads what it read before.
9+
10+
Why it matters: a rejection test on this path could only ever be a bare `toThrow()`, and a throw-shaped assertion stays green against an unrelated `Error` from anywhere on the path — measured when the install-time `DUPLICATE_ARTIFACT_OBJECT_NAME` check was ablated and its "refused" assertion stayed green because this refusal fired one step later. Rejection tests can now assert `code` + `status` on this path, and the existing sites that asserted only the message do.
11+
12+
Not narrowed, not widened: no accept-set changes. The ADR-0029 D9 §6.1 late-install branch (a tenant-authored sitting owner is re-classified as the code package's overlay layer) is not a refusal and is unchanged.
13+
14+
`@objectstack/runtime` carries the classification row for the new code in the dispatcher error-code vocabulary (verdict `boot-refusal`, door `none`: measured on this tree, every path to the refusal either aborts boot inside plugin init or catches below any HTTP door, and the two HTTP install sites never call `registerObject`).
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
"@objectstack/plugin-auth": patch
3+
"@objectstack/plugin-security": patch
4+
"@objectstack/service-i18n": patch
5+
---
6+
7+
fix(tooling): put three more package-root plugin manifests inside a tsc program (#14386)
8+
9+
`check:type-check-coverage`'s `isUncheckedSourceCandidate` skipped `depth === 0`
10+
(the package root) unconditionally, so a package-root `.ts` file was invisible
11+
to SOURCES_COVERED no matter what it contained — not reported, and not
12+
tracked either. That is exactly why #13284's `driver-memory` /
13+
`plugin-hono-server` manifests went unchecked for as long as they did:
14+
`pnpm --filter <pkg> typecheck` exited 0 with a file no tsc program read, and
15+
the coverage gate called the package COVERED at the same time.
16+
17+
This finds three more package-root manifest authoring sites the same hole
18+
hid, all `objectstack.config.ts`: `plugin-auth`, `plugin-security` and
19+
`service-i18n`. The gate now admits `depth === 0` only for a declared,
20+
exact-name allowlist (`ROOT_SOURCE_FILES`, `objectstack.config.ts` its only
21+
member) — not every root-level file, which stays the unresolved "104-file"
22+
scope question this card explicitly declines to settle (comment
23+
5504408509 on #14386) — and each of the three manifests now sits inside a
24+
program its package's own `typecheck` script invokes: a widened `include` on
25+
the existing sibling `noEmit` program for `plugin-auth`
26+
(`tsconfig.examples.json`) and `plugin-security` (`tsconfig.scripts.json`),
27+
and a new sibling `tsconfig.typecheck.json` for `service-i18n` (which had no
28+
sibling to widen), following the `driver-memory` shape #13284 established.
29+
30+
All three type-check clean at zero recorded debt — no ledger entry is added.

content/docs/ai/skills-reference.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ ObjectStack ships **11 skills** — one per authoring domain, plus process skill
4949
| 4 | [UI](#ui) | `ui` | `skills/objectstack-ui/` | Author ObjectStack UI metadata — Views (list/form/kanban/calendar/gantt), Apps (navigation), Pages (structured plus the HTML and React source-authoring tiers, ADR-0080/0081), Dashboards, Reports, Charts, Actions, and package Docs (`src/docs/*.md`). |
5050
| 5 | [Automation](#automation) | `automation` | `skills/objectstack-automation/` | Design ObjectStack automation — Flows (visual logic), Triggers, Approvals, state machines, scheduled jobs, and webhooks. |
5151
| 6 | [AI](#ai) | `ai` | `skills/objectstack-ai/` | Design ObjectStack AI skills, tools, knowledge sources, conversations, model registry entries, and MCP integrations. |
52-
| 7 | [API](#api) | `api` | `skills/objectstack-api/` | Design the server-side API surface that an ObjectStack runtime exposes — REST endpoints, auth providers, realtime channels, error envelopes, batch/versioning contracts. |
52+
| 7 | [API](#api) | `api` | `skills/objectstack-api/` | Design the server-side API surface that an ObjectStack runtime exposes — REST endpoints, auth providers, realtime channels, error envelopes, batch contracts. |
5353
| 8 | [i18n](#i18n) | `i18n` | `skills/objectstack-i18n/` | Author ObjectStack translation bundles — object/field labels, view text, app navigation strings, automation messages — and configure locale fallback, coverage reporting, and the per-locale source layout. |
5454
| 9 | [Formula](#formula) | `expression` | `skills/objectstack-formula/` | Author CEL expressions used across ObjectStack — formula fields, field conditional rules (`visibleWhen`, `readonlyWhen`, `requiredWhen`), validation / sharing / visibility predicates, flow conditions, and dynamic seed values. |
55-
| 10 | [PM Dispatch](#pm-dispatch) | `process` | `skills/objectstack-pm-dispatch/` | Run a project-manager dispatch loop over a GitHub backlog: triage and queue ready issues, claim each one, dispatch it to a parallel developer agent that returns a structured JSON report, review the results against GitHub, and drive accepted pull requests to landing — escalating to the maintainer only what genuinely needs a human decision. Ships the developer-agent operating template the loop injects into every dispatch (no custom agent types required) and the upstream-reporting procedure for platform defects an app project finds. |
55+
| 10 | [PM Dispatch](#pm-dispatch) | `process` | `skills/objectstack-pm-dispatch/` | Run a project-manager dispatch loop over a GitHub backlog: triage and queue ready issues, claim each one, dispatch it to a parallel developer agent that returns a structured JSON report, review the results against GitHub, and drive accepted pull requests to landing — escalating to the maintainer only what genuinely needs a human decision. Ships the developer-agent operating template the loop injects into every dispatch (no custom agent types required). |
5656
| 11 | [Upgrade](#upgrade) | `process` | `skills/objectstack-upgrade/` | Upgrade an ObjectStack metadata project across a protocol major — run the deterministic conversion chain, then work the semantic residue the chain cannot express (intent choices, custom code on retired APIs, stale prose) to a decision with the project's owner, and finish with a green `validate` plus a human-readable upgrade report. |
5757

5858
---
@@ -145,7 +145,7 @@ Do not use for general LLM prompting questions unrelated to ObjectStack metadata
145145

146146
**Domain** `api` · **Path** `skills/objectstack-api/`
147147

148-
Design the server-side API surface that an ObjectStack runtime exposes — REST endpoints, auth providers, realtime channels, error envelopes, batch/versioning contracts.
148+
Design the server-side API surface that an ObjectStack runtime exposes — REST endpoints, auth providers, realtime channels, error envelopes, batch contracts.
149149

150150
Use when the user is adding `*.endpoint.ts`, configuring auth providers, defining custom routes, or extending the REST generator.
151151

@@ -187,9 +187,9 @@ Do not use for SQL fragments (driver-native), cron schedules (cron dialect), or
187187

188188
**Domain** `process` · **Path** `skills/objectstack-pm-dispatch/`
189189

190-
Run a project-manager dispatch loop over a GitHub backlog: triage and queue ready issues, claim each one, dispatch it to a parallel developer agent that returns a structured JSON report, review the results against GitHub, and drive accepted pull requests to landing — escalating to the maintainer only what genuinely needs a human decision. Ships the developer-agent operating template the loop injects into every dispatch (no custom agent types required) and the upstream-reporting procedure for platform defects an app project finds.
190+
Run a project-manager dispatch loop over a GitHub backlog: triage and queue ready issues, claim each one, dispatch it to a parallel developer agent that returns a structured JSON report, review the results against GitHub, and drive accepted pull requests to landing — escalating to the maintainer only what genuinely needs a human decision. Ships the developer-agent operating template the loop injects into every dispatch (no custom agent types required).
191191

192-
Use when asked to "work through the backlog", "batch-dispatch issues", "派发 issue 给开发 agent", to stand up a multi-agent delivery loop in an ObjectStack app project, or to report a platform bug found while building an app.
192+
Use when asked to "work through the backlog", "batch-dispatch issues", "派发 issue 给开发 agent", or to stand up a multi-agent delivery loop in an ObjectStack app project.
193193

194194
Do not use for authoring ObjectStack metadata (the domain skills cover that), for a single already-scoped change you can just make, or as a replacement for the project's own conventions file — that file always wins.
195195

0 commit comments

Comments
 (0)