Skip to content

Commit 2f54564

Browse files
committed
Merge origin/main (ad7c351) into claude/issue-20751-services-strings-stage6
The prose-id ledger conflicted: main's copy was taken and regenerated with --census-ledger on the merged tree. Against main it deletes 16 lines and adds none: the plugin-sharing and audit-writers.ts entries go to zero and no other entry moves. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
2 parents 90db7d4 + ad7c351 commit 2f54564

429 files changed

Lines changed: 14971 additions & 3274 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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
'@objectstack/core': patch
3+
---
4+
5+
Provenance comments in `@objectstack/core` cite the commits that decided them, not tracker numbers that no longer resolve
6+
7+
Clause-②: no
8+
9+
Docblocks and comments across the package cited issue-tracker numbers that now answer 404 on GitHub.
10+
Each now cites the commit in this repository's history that made the decision it describes, except
11+
three source comments: one in `resolve-authz-context.ts` that quotes a maintainer ruling now cites
12+
ADR-0131's 2026-09-17 amendment, which records that ruling verbatim, and two on the unpack-time
13+
integrity re-verification leg, which pointed at a tracker for work that was never built, now say in
14+
words that the leg is unbuilt. One test comment named a maintainer-ruling comment that also answers
15+
404; it now cites ADR-0025 §3.7, which records that ruling's effect. Some of these docblocks sit on
16+
exported members, so the reworded text appears in the published declaration files (`index.d.ts` /
17+
`index.d.cts`), and the comments esbuild keeps appear in the JavaScript output (`index.js` /
18+
`index.cjs`).
19+
20+
Comment only: no export, type, error code, status, message text or runtime behaviour changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@objectstack/platform-objects': patch
3+
---
4+
5+
Provenance comments in `@objectstack/platform-objects` cite the commits that decided them, not tracker numbers that no longer resolve
6+
7+
Clause-②: no
8+
9+
Docblocks and comments across the package cited issue-tracker numbers that now answer 404 on GitHub.
10+
Each now cites the commit in this repository's history that made the decision it describes, except one
11+
that cites ADR-0104's 2026-09-05 addendum, the record of that ruling. Some of these docblocks sit on
12+
exported members, so the reworded text appears in the published declaration files (`apps`, `identity`,
13+
`metadata-translations` and `system` `index.d.ts` / `index.d.mts`), and the field comments esbuild keeps
14+
appear in the JavaScript output (`index`, `apps`, `audit`, `identity` and `plugin`, `.js` / `.mjs`).
15+
16+
Comment only: no export, type, error code, status, message text or runtime behaviour changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
'@objectstack/lint': patch
3+
---
4+
5+
Data-model, filter, predicate, search, sort, security, seed, view, widget and registry findings no longer cite tracker numbers; each one states the decision behind it in words
6+
7+
Clause-②: no
8+
9+
The remaining `@objectstack/lint` findings that `os validate`, `os lint` and `os build` show to authors, plus the `surfaceReason` texts of the exported `AUTHORING_RULES` registry and one integrity error, pointed at an issue-tracker number for the reason behind them. The number goes; where the sentence did not already say what was decided, it now does.
10+
11+
- Data model: the bare declared `unique: true` warning says that protocol 18 rejects the spelling and that stored metadata still carrying it converts to `unique: 'global'`, which builds the same physical index.
12+
- Empty filter combinators: the `$and: []`, `$or: []` and empty-node messages say every backend reduces an empty combinator to its boolean identity; the `$or: []` message says an empty disjunction never opens a read scope to the whole table.
13+
- Null guards: the fail-closed outcome says a predicate that cannot evaluate refuses the write rather than being skipped.
14+
- Visibility and metadata-form predicates: the fall-open consequence says failing open is the console's settled behaviour; the dotted right-hand-side message says the form evaluator keeps its right-hand side a literal by design and says why only in a development build.
15+
- Component props: the advisory hint says props are judged at the authoring door as a warning before they become an error.
16+
- Rule schema formats: the format hint says `rule-validator.ts` registers the default `ajv-formats` set so that a `format` is enforced on every write.
17+
- Security posture: the unset-OWD message describes the leave_request incident (an object with no `sharingModel` let an ordinary read/write grant read and edit every other user's records); the `controlled_by_parent` message says the write is refused as a metadata defect rather than a permission denial.
18+
- Seeds and views: the seed state-machine message says a seed records established facts rather than walking the lifecycle; the `views:` container message says the stack schema, the rule and the registration loop hold `views:` to one container-only contract.
19+
- React pages: the absent-`groupBy` hint states the ruling directly.
20+
- Liveness: the unrecognised-status integrity error says such a status fails loudly rather than being graded `dead`.
21+
- `AUTHORING_RULES` `surfaceReason` texts: the full-snapshot, capability-reference and sharing-rule reasons name the runtime publish gate (the Studio, REST and MCP door that runs this registry) in place of a tracker number; the advisory-volume reason says the object door opened to the gating object rules alone; the component-types reason names the crossing discipline the gating object rules went through.
22+
- The other findings (search fields, sort fields, nav servability, dashboard actions, widget bindings and the remaining predicate and combinator messages) drop a citation the sentence already explained.
23+
24+
Text only: no rule id, severity, condition, finding or registry field moves. A tool or test that matches the old text (for example a tracker-number suffix) needs the new spelling.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
Field-key guidance, the retired `DriverCapabilities` tombstones, the datasource `readOnly` guidance, the retired filter operators and the legacy `apiMethods` strip warning no longer cite tracker numbers; each one states the decision behind it in words
6+
7+
Clause-②: no
8+
9+
These are the `@objectstack/spec` texts an author meets at the moment something is refused or rewritten: the unknown-field-key guidance that `os validate` and the lint print, the parse errors for retired `DriverCapabilities` keys, the guidance for `readOnly` written inside a datasource driver's `config`, the `INVALID_FILTER` refusal every driver face prints for `$regex` / `$options`, and the warning `enable.apiMethods` prints when it strips a retired legacy value. They pointed at an issue-tracker number for the reason behind them. The number goes; where the sentence did not already say what was decided, it now does.
10+
11+
- Field-key guidance: `index` and `indexed` say the field-level index flag built no index and was removed under ADR-0049 enforce-or-remove; `dataQuality` and `cached` say their leftover `DataQualityRules` and `ComputedFieldCache` schemas were deleted from the public API too, and that computed-field caching returns only together with a runtime consumer.
12+
- `DriverCapabilities` tombstones: the `bulkCreate` / `bulkUpdate` / `bulkDelete` prescriptions name discovery's `transactionalBatch` bit, derived from the live composition so a client negotiates instead of probing; the `fullTextSearch` prescription says `$contains` itself stays case-sensitive while textual search is case-insensitive.
13+
- Datasource `readOnly` guidance: says a managed datasource has no read-only gate by decision, because a flag only the application checks cannot stop direct connections, migrations or DDL.
14+
- Retired filter operators: the `$regex` and `$options` refusals say they are retired under ADR-0049 enforce-or-remove, refused rather than reinterpreted.
15+
- Legacy `apiMethods` strip warning: the `restore` and `purge` prescriptions say `enable.trash` was retired because no runtime ever read it, and that the recycle-bin (soft-delete) work `restore` would need is parked.
16+
17+
Text only: no key, schema shape, condition, error code or status moves. A tool or test that matches the old text (for example a tracker-number suffix) needs the new spelling.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/service-automation': patch
3+
'@objectstack/plugin-audit': patch
4+
---
5+
6+
Automation refusals, prescriptions, log lines and run-object field help, and the activity type help, no longer cite tracker numbers; each one states the decision behind it in words
7+
8+
Clause-②: no
9+
10+
Some strings these two packages show to flow authors, operators and administrators pointed at an issue-tracker number for the reason behind them. The number goes; where the sentence did not already say what was decided, it now does.
11+
12+
- `@objectstack/service-automation`: the refusal for a `fieldValues` write map says a runtime alias for it was rejected by design, so the node keeps one strict `fields` key; the refusal for a screen field's `visibleIf` says a predicate under any other key is never read, so the field always shows, and a `required` field meant to stay hidden then blocks the screen from ever being submitted; the undeclared-config-key refusal says the built-in node types were reconciled so that every key their executors read is declared; the unknown-function error in a flow value expression says such a name is refused rather than evaluated to null, which would write the field as undefined; the inert-connector warning says entries without a `provider` are catalog descriptors, while an entry that names a `provider` is a connector instance that provider's installed executor materializes; the `sys_automation_run` field help says the paused node's type decides who may continue a run (an approval pause only through its owning service), that rows written before run history recorded its trigger were not backfilled, and that a finished run's bounded step log keeps its per-node detail across a restart; three bridge debug lines say what each bridge provides. The bulk-intent guidance, the degraded-connector dispatch error and retry lines, the user-less `runAs` warning and refusal, the unclaimed-branch warning, the script-function and node-config refusals and the `sys_flow_dispatch` description drop their citations.
13+
- `@objectstack/plugin-audit`: the `sys_activity` `type` help, whose English text all four shipped locale bundles carry, says the vocabulary is open by decision, not a gap awaiting enforcement.
14+
15+
Text only: no status, error code, field, route or control flow moves. A client or log filter that matches the old text (for example a tracker-number suffix) needs the new spelling.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
'@objectstack/plugin-security': patch
3+
---
4+
5+
Security refusals, explain details, field help and log lines no longer cite tracker numbers; each one states the decision behind it in words
6+
7+
Clause-②: no
8+
9+
Some strings the security plugin shows to administrators, authors and operators pointed at an issue-tracker number for the reason behind them. The number goes; where the sentence did not already say what was decided, it now does.
10+
11+
- The curated capability-name refusal says a curated name is refused at authoring so that no admin-authored row can collide with the row the platform seeds for it.
12+
- The two delegation anchor refusals say the business-unit anchor roots the delegate's business-unit visibility, so a delegation may only narrow it.
13+
- The `managed_by` field help on `sys_permission_set` and `sys_position`, in every shipped locale, says capabilities, permission sets and positions all share one platform / package / admin vocabulary.
14+
- The explain details for an unresolvable security posture and for the View/Modify All Data bypass drop their citations; those sentences already said that access fails closed and that the write path consults the same bypass.
15+
- The derived-capability boot warning says the derivation refreshes a row's label and description only when it can prove the row is the platform's own, and that the seeder neither adopts a row it cannot prove is its own nor backfills provenance on the operator's behalf.
16+
- The fail-closed log lines say what each denial protects: a `controlled_by_parent` child is readable and writable only where its master is, and a chain the derivation cannot resolve admits no child; only a resolved sharing allow (Modify All Data or an edit-level share) may replace the platform ownership floor; an authored-policy verdict that cannot be resolved never lifts the sharing refusal; a path that bypasses the engine middleware never runs without the owner and share scope a direct read applies; a delegated read is never scoped wider than its delegator's own; an unreadable posture never defaults to public or uncontracted.
17+
- The public-form line says an anonymous submission cannot set ownership, tenancy or audit columns; the uninstall line says a package's permission rows are removed by `package_id`, so no grant outlives the package; the platform-owner wall-bypass line says only the declared platform owner's reads cross the wall and writes stay walled for everyone. The org-scoping entitlement, masking-rule, permission-set resolution, vocabulary-normalization and service-registration lines drop their citations, and the log lines that carried a tracker number in their `[security/…]` prefix now open with `[security]`.
18+
19+
Text only: no status, error code, field, route or control flow moves. A client or log filter that matches the old text (for example a tracker-number suffix or prefix) needs the new spelling.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/platform-objects': patch
4+
---
5+
6+
feat(spec)!: retire `agent.lifecycle`, the agent conversation state machine, and with it the XState `StateMachineSchema` family — a conversation phase is a skill with `triggerConditions`, orchestration is Flow, record transitions are the `state_machine` validation rule (#21320)
7+
8+
**BREAKING** — `agent.lifecycle` was parsed and never read. No runtime, in this
9+
repository or in the cloud AI runtime that executes agents, moved an agent through a
10+
declared state or refused an undeclared transition, so an authored machine changed
11+
nothing an agent did (ADR-0049 enforce-or-remove). Enforcing it would have meant a
12+
statechart interpreter beside Flow, the two-engine shape ADR-0020 rejected. Authoring
13+
now refuses the key by name, with a prescription, and TypeScript rejects it.
14+
15+
Its value schema had no other authorable door: ADR-0020 had already retired the XState
16+
shape as a record-lifecycle declaration and kept the file only for this key. So the
17+
family leaves the package with it.
18+
19+
### FROM → TO
20+
21+
| before | what to write instead |
22+
| --- | --- |
23+
| `agent.lifecycle` — any value | delete the key. |
24+
| a conversation phase in the machine (its own instructions and tools) | a skill with its own `instructions` and `tools`, selected by its `triggerConditions`, listed in the agent's `skills`. |
25+
| a multi-step process in the machine | a Flow. |
26+
| a record's status transitions in the machine | a `state_machine` validation rule in the object's `validations`: `{ type: 'state_machine', field, transitions: { from: [to, …] } }`. |
27+
| `StateMachineSchema`, `StateNodeSchema`, `TransitionSchema`, `ActionRefSchema`, `GuardRefSchema` and the types `StateMachineConfig`, `StateNode`, `StateNodeConfig`, `Transition`, `ActionRef`, `GuardRef` from `@objectstack/spec/automation` | no replacement: declare the shape your code needs itself, or drop it. For record transitions, `StateMachineValidationSchema` in `@objectstack/spec/data` is the enforced shape. |
28+
| `StateNodeConfig` from `@objectstack/spec` or `@objectstack/spec/ai` | removed with the family; nothing in those entries mentions it any more. |
29+
30+
**The one-line fix: delete `lifecycle`; put phase-scoped instructions and tools in
31+
skills with `triggerConditions`, and orchestration in Flow.** `os migrate meta --from 17`
32+
lists the mechanical edits for existing sources (the `lifecycle` deletion). Where each
33+
deleted machine's intent goes is the author's judgement.
34+
35+
The refusal is a parse error at `lifecycle` naming the key and the fix, and the key
36+
fails `tsc` (its input type is `never`).
37+
38+
### The retirement kit
39+
40+
- **Tombstone.** `lifecycle` is a `retiredKey()` on `AgentSchema` carrying the
41+
prescription; the agent metadata form no longer offers it.
42+
- **D2 conversion `agent-lifecycle-removed`** (step 18, retired from the load path):
43+
it deletes `lifecycle` from every agent, whatever it holds. The delete is lossless,
44+
because no value of it ever changed what an agent did. Stored `sys_metadata` agent
45+
rows and built artifacts replay it; one notice per agent. An object's ADR-0057
46+
`lifecycle` block shares the name and is not touched.
47+
- **D3 entry `agent-lifecycle-retired`** carries the judgement the conversion cannot
48+
make: which of the three destinations each deleted machine meant.
49+
- **`RETIRED_KEYS_BY_MAJOR[18]`** registers `ai/Agent:lifecycle`, and
50+
**`RETIRED_DEFS_BY_MAJOR[18]`** registers the five published defs
51+
`automation/StateMachine`, `automation/StateNode`, `automation/Transition`,
52+
`automation/ActionRef` and `automation/GuardRef`. Their reference page
53+
(`references/automation/state-machine`) is gone.
54+
- **No deprecation window**, per the project's startup-stage posture.
55+
56+
### The liveness ledger
57+
58+
The `agent.lifecycle` row moves `experimental` → `dead` with a REMOVED note
59+
(`verifiedAt` 2026-10-02); the tombstone keeps it in the walked shape. No `agent` row is
60+
`experimental` any more. `os validate` and every other parsing door refuse the key at
61+
parse, before any advisory runs. `os lint` reads the unparsed stack, so it now grades the
62+
key `liveness-dead-property` where it used to say `liveness-experimental-property`.
63+
64+
### `@objectstack/platform-objects`
65+
66+
The agent metadata-form catalogs drop the `lifecycle` row's label and help text in all
67+
four locales.
68+
69+
⚠️ **The out-of-repo consumer population is NOT MEASURED.** `@objectstack/spec` is
70+
published: tenant-authored agents, and code outside this repository importing the
71+
family's exports, were not measured. This repository authors no `agent.lifecycle`
72+
outside `packages/spec` and imports none of the family outside it; the pinned objectui
73+
checkout imports none of the family and reads no `agent.lifecycle`.
74+
75+
Clause-②: yes (narrowing)
76+
77+
<!-- adr-0087: registered agent-lifecycle-removed, agent-lifecycle-retired -->
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
"@objectstack/cloud-connection": patch
3+
"@objectstack/plugin-security": patch
4+
---
5+
6+
fix(cloud-connection,plugin-security): a package installed into a running runtime fires its record-change flows and has its permission sets in `sys_permission_set` right away, not after a restart
7+
8+
Clause-②: no
9+
10+
**Before**, `os package install ./dist/objectstack.json` into a running `os start` (the install-local route) registered the package, bound its script actions and body hooks, and stopped there. Two things the boot does for a package happen at `kernel:ready`, and that moment had already passed. The automation engine binds flows at `kernel:ready`, so the package's record-change flows never fired: a task updated to `done` wrote no note. The security plugin seeds declared permission sets at `kernel:ready`, so the package's set had no `sys_permission_set` row. `/meta/permission` listed the set, but an admin could not grant it. A restart fixed both, because the restart re-registers the package before those two steps run. Nothing in the CLI output or the install response said a restart was needed.
11+
12+
**Now** the install route announces `metadata:reloaded` once the package is registered, bound, persisted and seeded. That is the same event a Studio package publish, a per-item publish and an artifact reload already announce. The automation engine already re-syncs its flows on it. The security plugin now re-runs its declared-permission seeding on it: the same function and organization passes as the boot, with the same provenance rules (`managed_by: 'package'`, `package_id`). Right after the install, the flow fires and the set's row exists, with the same state a restart gives. The seeding is idempotent and writes nothing when no permission set changed. It runs only after the boot's own pass has finished. A failed re-sync does not fail the install. It is logged at `warn` with the restart that repairs it.
13+
14+
**Unchanged.** The restart path (the ledger rehydrate) announces nothing and behaves as before. The install response and the CLI output keep their fields and text. A package's `defineStack({ jobs })` are still not scheduled by install-local, on install or after a restart, because a job's handler is code from the artifact's runtime module and an inline install carries only the JSON.

0 commit comments

Comments
 (0)